详解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通过scapy获取局域网所有主机mac地址示例
May 04 Python
python 回调函数和回调方法的实现分析
Mar 23 Python
python列表的常用操作方法小结
May 21 Python
教你用Type Hint提高Python程序开发效率
Aug 08 Python
python实现折半查找和归并排序算法
Apr 14 Python
python自动12306抢票软件实现代码
Feb 24 Python
Python基于Flask框架配置依赖包信息的项目迁移部署
Mar 02 Python
Python3.4 splinter(模拟填写表单)使用方法
Oct 13 Python
Python补齐字符串长度的实例
Nov 15 Python
Python协程 yield与协程greenlet简单用法示例
Nov 22 Python
Python实现钉钉订阅消息功能
Jan 14 Python
python 爬取腾讯视频评论的实现步骤
Feb 18 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 cli换行示例
2014/04/22 PHP
PHP使Laravel为JSON REST API返回自定义错误的问题
2018/10/16 PHP
Laravel5.7 数据库操作迁移的实现方法
2019/04/12 PHP
PHP利用pdo_odbc实现连接数据库示例【基于ThinkPHP5.1搭建的项目】
2019/05/13 PHP
用js实现的页面关键字密度查询代码
2007/12/27 Javascript
js获取div高度的代码
2008/08/09 Javascript
封装的原生javascript弹出层代码
2010/09/24 Javascript
js中opener与parent的区别详细解析
2014/01/14 Javascript
代码获取历史上的今天发生的事
2014/04/11 Javascript
HTML5之WebSocket入门3 -通信模型socket.io
2015/08/21 Javascript
JS实现的竖向折叠菜单代码
2015/10/21 Javascript
JavaScript操作HTML DOM节点的基础教程
2016/03/11 Javascript
js 获取经纬度的实现方法
2016/06/20 Javascript
js 点击a标签 获取a的自定义属性方法
2016/11/21 Javascript
ajax异步请求详解
2017/01/06 Javascript
js脚本编写简单刷票投票系统
2017/06/27 Javascript
详解vue-cli项目中用json-sever搭建mock服务器
2017/11/02 Javascript
vue+vuex+axios实现登录、注册页权限拦截
2018/03/09 Javascript
bootstrap与pagehelper实现分页效果
2018/12/29 Javascript
webpack 最佳配置指北(推荐)
2020/01/07 Javascript
jquery实现轮播图特效
2020/04/12 jQuery
如何用JS模拟实现数组的map方法
2020/07/30 Javascript
JS实现可以用键盘方向键控制的动画
2020/12/11 Javascript
python获取Linux下文件版本信息、公司名和产品名的方法
2014/10/05 Python
说一说Python logging
2016/04/15 Python
详解Django中间件执行顺序
2018/07/16 Python
python bluetooth蓝牙信息获取蓝牙设备类型的方法
2019/11/29 Python
python中os包的用法
2020/06/01 Python
python实现mask矩阵示例(根据列表所给元素)
2020/07/30 Python
办公室经理岗位职责
2014/01/01 职场文书
工厂搬迁方案
2014/05/11 职场文书
金砖之国观后感
2015/06/11 职场文书
2019年浪漫婚礼证婚词
2019/06/27 职场文书
《思路决定出路》读后感3篇
2019/12/11 职场文书
通过Qt连接OpenGauss数据库的详细教程
2021/06/23 PostgreSQL
Oracle中日期的使用方法实例
2022/07/07 Oracle