python实现kmp算法的实例代码


Posted in Python onApril 03, 2019

kmp算法

kmp算法用于字符串的模式匹配,也就是找到模式字符串在目标字符串的第一次出现的位置

比如

abababc

那么bab在其位置1处,bc在其位置5处

我们首先想到的最简单的办法就是蛮力的一个字符一个字符的匹配,但那样的时间复杂度会是O(m*n)

kmp算法保证了时间复杂度为O(m+n)

基本原理

举个例子:

python实现kmp算法的实例代码

发现x与c不同后,进行移动

python实现kmp算法的实例代码

a与x不同,再次移动

python实现kmp算法的实例代码

此时比较到了c与y,
于是下一步移动成了下面这样

python实现kmp算法的实例代码

这一次的移动与前两次的移动不同,之前每次比较到上面长字符串的字符位置后,直接把模式字符串的首字符与它对齐,这次并没有,原因是这次移动之前,y与c对齐,但是y前边的ab是与自己的前缀ab一样,于是ab并不用再比较,直接从第三个位置开始比较,如图:

python实现kmp算法的实例代码

所以说kmp算法对于这种情况就直接使用当前比较字符之前的最长相同的前后缀,然后将前缀与上面的长字符串对齐,继续比

较后面的字符串。
这里kmp算法中的一个重要点就来了,如何找到模式字符串中每位字符之前的最长相同前后缀呢
这里继续用一个例子举例:

python实现kmp算法的实例代码

下面的数字记录以该字符为结尾的最长前后缀相同子串的长度,先初始化为0,并且第一个字符下的数字确认为0
然后开始比较:

python实现kmp算法的实例代码

a与b不同,那么b下的数字也为0同理a与c不同,c下的数字也为0,接下来a与a对齐,如下

python实现kmp算法的实例代码

此时a与a相同,那么a下面的数字为1,也就是第二排字符串中当前比对的字符索引+1
接下来b与b相同,c与a不相同,那么此时上面的字符串不动,下面的字符串移动到当前比对位置即c的前一位的下方的数字的位置,如图:

移动前

python实现kmp算法的实例代码

c的前一位是b,b下方的数字是0,所以将下面字符串的第0位与之前的比对位置对其,即:

python实现kmp算法的实例代码

当前比对位置如箭头所示,然后继续向后比较,一直比到c与a:

python实现kmp算法的实例代码

此时c与a不相同,那么比较下面字符的前一个字符的下方数字的位置,如图

python实现kmp算法的实例代码

也就是位置为2的地方与上面比对位置对齐:

python实现kmp算法的实例代码

此时c与c相同,整个字符串自比对完成:

python实现kmp算法的实例代码

此时可能会没有理解为什么匹配不成功的时候要再比对其前一位字符下的数字的位置,那是因为这是要找到前一个字符位置下的最长相同前缀中的最长相同前缀,就举刚才的例子:

python实现kmp算法的实例代码

此时a前边是abcab,所以要找到abcab的最长相同前缀,就是ab,这时

python实现kmp算法的实例代码

然后再移动到ab与ab对其的位置继续比较即可

时间复杂度

简单来讲, 找到模式字符串中每位字符之前的最长相同前后缀的这个方法中,如果模式字符串的长度为m,那么上面的字符串的指向是一直向前移动的,下面字符串的整体也是一直向前移动的,最终移动的结果将会是长度为2m,所以比较次数也是最大为2m,时间复杂度为O(m)

kmp算法中,运用了找到模式字符串中每位字符之前的最长相同前后缀的这个方法的结果,然后使用类似的方法进行比较和移动,和上边的解释类似,如果这个要匹配的字符串长度为n,那最长的移动举例也超不过2n,所以总的时间复杂度为O(m+n)

具体代码

这里没有进行传入参数的验证,使用时还要注意。

def same_start_end(s):
  """最长前后缀相同的字符位数"""
  n = len(s) #整个字符串长度
  j = 0 # 前缀匹配指向
  i = 1 # 后缀匹配指向
  result_list=[0]*n
  while i < n:
    if j == 0 and s[j] != s[i]: # 比较不相等并且此时比较的已经是第一个字符了
      result_list[i] = 0  # 值为0
      i += 1 # 向后移动
    elif s[j] != s[i] and j != 0: #比较不相等,将j值设置为j前一位的result_list中的值,为了在之前匹配到的子串中找到最长相同前后缀
      j = result_list[j-1]
    elif s[j] == s[i]:  #相等则继续比较
      result_list[i] = j+1
      j = j+1
      i = i+1
  return result_list
def kmp(s,p):
  """kmp算法,s是字符串,p是模式字符串,返回值为匹配到的第一个字符串的第一个字符的索引,没匹配到返回-1"""
  s_length = len(s)
  p_length = len(p)
  i = 0 # 指向s
  j = 0 # 指向p
  next = same_start_end(p)
  while i < s_length:
    if s[i] == p[j]: # 对应字符相同
      i += 1
      j += 1
      if j >= p_length: # 完全匹配
        return i-p_length
    elif s[i] != p[j]: # 不相同
      if j == 0:  # 与模式比较的是模式的第一个字符
        i += 1
      else:    # 取模式当前字符之前最长相同前后缀的前缀的后一个字符继续比较
        j = next[j]
  if i == s_length:  # 没有找到完全匹配的子串
    return -1

总结

以上所述是小编给大家介绍的python实现kmp算法的实例代码,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

Python 相关文章推荐
python使用urlparse分析网址中域名的方法
Apr 15 Python
Python的__builtin__模块中的一些要点知识
May 02 Python
Python创建对称矩阵的方法示例【基于numpy模块】
Oct 12 Python
解决pycharm py文件运行后停止按钮变成了灰色的问题
Nov 29 Python
Python使用post及get方式提交数据的实例
Jan 24 Python
pyqt5 使用label控件实时显示时间的实例
Jun 14 Python
python读写csv文件的方法
Aug 13 Python
python 协程中的迭代器,生成器原理及应用实例详解
Oct 28 Python
Python列表原理与用法详解【创建、元素增加、删除、访问、计数、切片、遍历等】
Oct 30 Python
python+opencv3.4.0 实现HOG+SVM行人检测的示例代码
Jan 28 Python
Python OpenCV 彩色与灰度图像的转换实现
Jun 05 Python
Pytorch可视化的几种实现方法
Jun 10 Python
详解python多线程之间的同步(一)
Apr 03 #Python
Python将列表数据写入文件(txt, csv,excel)
Apr 03 #Python
详解python读取image
Apr 03 #Python
Python小白必备的8个最常用的内置函数(推荐)
Apr 03 #Python
查看python安装路径及pip安装的包列表及路径
Apr 03 #Python
元组列表字典(莫烦python基础)
Apr 03 #Python
python3 字符串/列表/元组(str/list/tuple)相互转换方法及join()函数的使用
Apr 03 #Python
You might like
造就帕卡马拉的帕卡斯是怎么被发现的
2021/03/03 咖啡文化
PHP新手上路(十四)
2006/10/09 PHP
php date()日期时间函数详解
2010/05/16 PHP
php数组声明、遍历、数组全局变量使用小结
2013/06/05 PHP
PHP5常用函数列表(分享)
2013/06/07 PHP
变量在 PHP7 内部的实现(一)
2015/12/21 PHP
php自定义函数实现二维数组按指定key排序的方法
2016/09/29 PHP
laravel高级的Join语法详解以及使用Join多个条件
2019/10/16 PHP
XmlUtils JS操作XML工具类
2009/10/01 Javascript
关于Javascript作用域链的八点总结
2013/12/06 Javascript
javascript实现获取cookie过期时间的变通方法
2014/08/14 Javascript
nodejs教程之异步I/O
2014/11/21 NodeJs
JavaScript生成福利彩票双色球号码
2015/05/15 Javascript
JavaScript如何实现在文本框(密码框)输入提示语
2015/12/25 Javascript
jQuery+php实时获取及响应文本框输入内容的方法
2016/05/24 Javascript
JavaScript中最容易混淆的作用域、提升、闭包知识详解(推荐)
2016/09/05 Javascript
bootstrap table单元格新增行并编辑
2017/05/19 Javascript
JS请求servlet功能示例
2017/06/01 Javascript
微信小程序实现列表页的点赞和取消点赞功能
2018/11/02 Javascript
Vue中的情侣属性$dispatch和$broadcast详解
2019/03/07 Javascript
JS可断点续传文件上传实现代码解析
2020/07/30 Javascript
[36:52]DOTA2真视界:基辅特锦赛总决赛
2017/05/21 DOTA
python实现带声音的摩斯码翻译实现方法
2015/05/20 Python
python 根据pid杀死相应进程的方法
2017/01/16 Python
Python matplotlib 画图窗口显示到gui或者控制台的实例
2018/05/24 Python
HTML5拖放效果的实现代码
2016/11/17 HTML / CSS
速比涛英国官网:Speedo英国
2019/07/15 全球购物
中科软笔试题和面试题
2014/10/07 面试题
开展党的群众路线教育实践活动总结报告
2014/10/31 职场文书
大学生求职简历自我评价
2015/03/02 职场文书
2015年社区综治宣传月活动总结
2015/03/25 职场文书
幼儿园工作总结2015
2015/04/01 职场文书
创业计划书介绍
2019/04/24 职场文书
职场新人刚入职工作总结该怎么写?
2019/05/15 职场文书
Java各种比较对象的方式的对比总结
2021/06/20 Java/Android
如何解决springcloud feign 首次调用100%失败的问题
2021/06/23 Java/Android