详解KMP算法以及python如何实现


Posted in Python onSeptember 18, 2020

算法思路

Knuth-Morris-Pratt(KMP)算法是解决字符串匹配问题的经典算法,下面通过一个例子来演示一下:

给定字符串"BBC ABCDAB ABCDABCDABDE",检查里面是否包含另一个字符串"ABCDABD"。

1.从头开始依次匹配字符,如果不匹配就跳到下一个字符

详解KMP算法以及python如何实现

详解KMP算法以及python如何实现

2.直到发现匹配字符,然后经过一个内循环严查字符串是否匹配

 详解KMP算法以及python如何实现

3.发现最后一个D不匹配,下面就该思考应该把字符串向右移动多少个位置呢?传统做法可能是移动一格,KMP算法就创新在这里。KMP算法通过查询一个Partial Match Table(表内存有字符串信息),然后计算出需要移动的步数,这个表后面会介绍怎么来的。

详解KMP算法以及python如何实现

这里我们看到D前面是B,查表得到第二个B对应的是2,所以 移动数 = 已匹配字符数 - 查表所得数 也就是 6 - 2 = 4, 需要向右移动四格。

详解KMP算法以及python如何实现

下面也是重复这个步骤

详解KMP算法以及python如何实现

直到发现匹配或者字符长度超出(未发现匹配)。

Partial Match Table

那么这个查询的表是怎么来的呢?仍然以"ABCDABD"为例

详解KMP算法以及python如何实现

- "A"的前缀和后缀都为空集,共有元素的长度为0;

- "AB"的前缀为[A],后缀为[B],共有元素的长度为0;

- "ABC"的前缀为[A, AB],后缀为[BC, C],共有元素的长度0;

- "ABCD"的前缀为[A, AB, ABC],后缀为[BCD, CD, D],共有元素的长度为0;

- "ABCDA"的前缀为[A, AB, ABC, ABCD],后缀为[BCDA, CDA, DA, A],共有元素为"A",长度为1;

- "ABCDAB"的前缀为[A, AB, ABC, ABCD, ABCDA],后缀为[BCDAB, CDAB, DAB, AB, B],共有元素为"AB",长度为2;

- "ABCDABD"的前缀为[A, AB, ABC, ABCD, ABCDA, ABCDAB],后缀为[BCDABD, CDABD, DABD, ABD, BD, D],共有元素的长度为0。

python实现

def partial_table(p):
  '''''partial_table("ABCDABD") -> [0, 0, 0, 0, 1, 2, 0]'''
  prefix = set()
  res = [0]
  for i in range(1, len(p)):
    prefix.add(p[:i])
    postfix = {p[j:i + 1] for j in range(1, i + 1)}
    #print(p[:i+1],prefix,postfix,prefix & postfix or {''})
    res.append(len((prefix & postfix or {''}).pop()))
  return res

def kmp_match(s, p):
  m = len(s);
  n = len(p)
  cur = 0 # 起始指针cur
  table = partial_table(p)
  while cur <= m - n:   #只去匹配前m-n个
    for i in range(n):
      if s[i + cur] != p[i]:
        cur += max(i - table[i - 1], 1) # 有了部分匹配表,我们不只是单纯的1位1位往右移,可以一次移动多位
        break
    else:    
      return True # loop从 break 中退出时,else 部分不执行。
  return False

print partial_table1("ABCDABD")
print kmp_match("BBC ABCDAB ABCDABCDABDE", "ABCDABD")

以上就是详解KMP算法以及python如何实现的详细内容,更多关于python实现KMP算法的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python os模块学习笔记
Jun 21 Python
简单谈谈python中的Queue与多进程
Aug 25 Python
python selenium自动上传有赞单号的操作方法
Jul 05 Python
python判断计算机是否有网络连接的实例
Dec 15 Python
Python设计模式之代理模式实例详解
Jan 19 Python
关于Python3 类方法、静态方法新解
Aug 30 Python
PyTorch的自适应池化Adaptive Pooling实例
Jan 03 Python
python实现简单井字棋小游戏
Mar 05 Python
Python发送邮件封装实现过程详解
May 09 Python
Python 实现将某一列设置为str类型
Jul 14 Python
pip已经安装好第三方库但pycharm中import时还是标红的解决方案
Oct 09 Python
Django框架模板用法详解
Jun 10 Python
python实现二分查找算法
Sep 18 #Python
Python自定义sorted排序实现方法详解
Sep 18 #Python
python爬虫爬取网页数据并解析数据
Sep 18 #Python
Python实现迪杰斯特拉算法过程解析
Sep 18 #Python
Python 操作 MySQL数据库
Sep 18 #Python
python实现人工蜂群算法
Sep 18 #Python
Python猫眼电影最近上映的电影票房信息
Sep 18 #Python
You might like
第七节 类的静态成员 [7]
2006/10/09 PHP
有关 PHP 和 MySQL 时区的一点总结
2008/03/26 PHP
PHP实现Socket服务器的代码
2008/04/03 PHP
ecshop 2.72如何修改后台访问地址
2015/03/03 PHP
JavaScript 基础问答三
2008/12/03 Javascript
JQuery中的$.getJSON 使用说明
2011/03/10 Javascript
JS正则中的RegExp对象对象
2012/11/07 Javascript
fixedBox固定div漂浮代码支持ie6以上大部分主流浏览器
2014/06/26 Javascript
js控制元素显示在屏幕固定位置及监听屏幕高度变化的方法
2015/08/11 Javascript
js使用cookie记录用户名的方法
2015/11/26 Javascript
基于JavaScript实现全屏透明遮罩div层锁屏效果
2016/01/26 Javascript
Angular中的interceptors拦截器
2017/06/25 Javascript
解决Jstree 选中父节点时被禁用的子节点也会选中的问题
2017/12/27 Javascript
详解如何在react中搭建d3力导向图
2018/01/12 Javascript
手把手带你封装一个vue component第三方库
2019/02/14 Javascript
在微信小程序中使用vant的方法
2019/06/07 Javascript
微信小程序如何实现五星评价功能
2019/10/15 Javascript
python中模块的__all__属性详解
2017/10/26 Python
python爬虫之模拟登陆csdn的实例代码
2018/05/18 Python
pytorch的梯度计算以及backward方法详解
2020/01/10 Python
Python如何访问字符串中的值
2020/02/09 Python
Python3自定义http/https请求拦截mitmproxy脚本实例
2020/05/11 Python
python文件及目录操作代码汇总
2020/07/08 Python
解决Python安装cryptography报错问题
2020/09/03 Python
python super()函数的基本使用
2020/09/10 Python
用HTML5实现网站在windows8中贴靠的方法
2013/04/21 HTML / CSS
俄罗斯品牌服装和鞋子在线商店:BRIONITY
2020/03/26 全球购物
使用索引(Index)有哪些需要考虑的因素
2016/10/19 面试题
微型企业创业投资计划书
2014/01/10 职场文书
销售人员获奖感言
2014/02/05 职场文书
保安部任务及岗位职责
2014/02/25 职场文书
群众路线教育党课主持词
2014/04/01 职场文书
迎七一演讲稿
2014/09/12 职场文书
党政领导班子民主生活会整改措施
2014/09/18 职场文书
七年级写作指导之游记作文
2019/10/07 职场文书
您对思维方式了解多少?
2019/12/09 职场文书