详解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刷投票的脚本实现代码
Nov 08 Python
Python基于select实现的socket服务器
Apr 13 Python
python实现媒体播放器功能
Feb 11 Python
python Opencv将图片转为字符画
Feb 19 Python
python_opencv用线段画封闭矩形的实例
Dec 05 Python
对python指数、幂数拟合curve_fit详解
Dec 29 Python
Python函数基础实例详解【函数嵌套,命名空间,函数对象,闭包函数等】
Mar 30 Python
Python基础学习之函数方法实例详解
Jun 18 Python
windows下python安装pip方法详解
Feb 10 Python
scrapy数据存储在mysql数据库的两种方式(同步和异步)
Feb 18 Python
Jupyter加载文件的实现方法
Apr 14 Python
python和php哪个容易学
Jun 19 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
PHP MemCached高级缓存配置图文教程
2010/08/05 PHP
ThinkPHP采用GET方式获取中文参数查询无结果的解决方法
2014/06/26 PHP
php实现发送微信模板消息的方法
2015/03/07 PHP
深入解析PHP中SESSION反序列化机制
2017/03/01 PHP
PHP基于自定义函数实现的汉字转拼音功能实例
2017/09/30 PHP
wordpress自定义标签云与随机获取标签的方法详解
2019/03/22 PHP
JavaScript For Beginners(转载)
2007/01/05 Javascript
动态创建script标签实现跨域资源访问的方法介绍
2014/02/28 Javascript
浏览器缩放检测的js代码
2014/09/28 Javascript
javascript原型链继承用法实例分析
2015/01/28 Javascript
jquery实现对联广告的方法
2015/02/05 Javascript
微信中一些常用的js方法汇总
2015/03/12 Javascript
js数组去重的方法汇总
2015/07/29 Javascript
jQuery插件WebUploader实现文件上传
2016/11/07 Javascript
Vue2.0表单校验组件vee-validate的使用详解
2017/05/02 Javascript
纯js实现动态时间显示
2020/09/07 Javascript
vue 路由嵌套高亮问题的解决方法
2018/05/17 Javascript
如何使用 vue + d3 画一棵树
2018/12/03 Javascript
Vue+abp微信扫码登录的实现代码示例
2020/01/06 Javascript
javascript中call,apply,bind的区别详解
2020/12/11 Javascript
[03:55]DOTA2完美大师赛选手传记——LFY.MONET
2017/11/18 DOTA
Python 调用VC++的动态链接库(DLL)
2008/09/06 Python
Django中URLconf和include()的协同工作方法
2015/07/20 Python
python实现员工管理系统
2018/01/11 Python
python K近邻算法的kd树实现
2018/09/06 Python
python得到电脑的开机时间方法
2018/10/15 Python
Python2与Python3的区别实例分析
2019/04/11 Python
python lambda函数及三个常用的高阶函数
2020/02/05 Python
Python实现Keras搭建神经网络训练分类模型教程
2020/06/12 Python
Python 代码调试技巧示例代码
2020/08/11 Python
系统管理员的职责包括那些?管理的对象是什么?
2013/01/18 面试题
Ruby如何进行文件操作
2014/07/17 面试题
2014元旦晚会策划方案
2014/02/19 职场文书
就业协议书的作用
2014/04/11 职场文书
《春雨》教学反思
2014/04/24 职场文书
运动会拉拉队口号
2014/06/09 职场文书