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实现统计文本文件字数的方法
May 05 Python
Python编程实现从字典中提取子集的方法分析
Feb 09 Python
对Python中的@classmethod用法详解
Apr 21 Python
详解Python网络框架Django和Scrapy安装指南
Apr 01 Python
python面试题小结附答案实例代码
Apr 11 Python
Python判断对象是否为文件对象(file object)的三种方法示例
Apr 26 Python
python调用webservice接口的实现
Jul 12 Python
python redis连接 有序集合去重的代码
Aug 04 Python
python实现连续变量最优分箱详解--CART算法
Nov 22 Python
jupyter notebook 恢复误删单元格或者历史代码的实现
Apr 17 Python
python如何导出微信公众号文章方法详解
Aug 31 Python
python集合的新增元素方法整理
Dec 07 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/02 无线电
PHP header()函数使用详细(301、404等错误设置)
2013/04/17 PHP
php封装的数据库函数与用法示例【参考thinkPHP】
2016/11/08 PHP
ASP.NET中使用后端代码注册脚本 生成JQUERY-EASYUI的界面错位的解决方法
2010/06/12 Javascript
JS实现的省份级联实例代码
2013/06/24 Javascript
从jquery的过滤器.filter()方法想到的
2013/09/29 Javascript
jQuery+ajax中getJSON() 用法实例
2014/12/22 Javascript
Javascript中的方法和匿名方法实例详解
2015/06/13 Javascript
整理关于Bootstrap模态弹出框的慕课笔记
2017/03/29 Javascript
jQuery Json数据格式排版高亮插件json-viewer.js使用方法详解
2017/06/12 jQuery
教你使用vue-cli快速构建的小说阅读器
2019/05/13 Javascript
vue+vant实现购物车全选和反选功能
2020/11/17 Vue.js
利用Python实现颜色色值转换的小工具
2016/10/27 Python
Python竟能画这么漂亮的花,帅呆了(代码分享)
2017/11/15 Python
python实现堆和索引堆的代码示例
2018/03/19 Python
浅谈dataframe中更改列属性的方法
2018/07/10 Python
Python图像处理之图像的读取、显示与保存操作【测试可用】
2019/01/04 Python
Python3中lambda表达式与函数式编程讲解
2019/01/14 Python
执行Django数据迁移时报 1091错误及解决方法
2019/10/14 Python
python tkinter的消息框模块(messagebox,simpledialog)
2020/11/07 Python
使用CSS3实现input多选框自定义样式的方法示例
2019/07/19 HTML / CSS
h5使用canvas画布实现手势解锁
2019/01/04 HTML / CSS
链表面试题-一个链表的结点结构
2015/05/04 面试题
中科前程Java笔试题
2016/11/20 面试题
大门门卫岗位职责
2013/11/30 职场文书
小学国庆节活动方案
2014/02/11 职场文书
研修第一天随笔感言
2014/02/15 职场文书
《火烧云》教学反思
2014/04/12 职场文书
环境科学专业教师求职信
2014/07/12 职场文书
改革共识倡议书
2014/08/29 职场文书
2014年党员自我评议(5篇)
2014/09/12 职场文书
就业协议书
2014/09/12 职场文书
党员个人剖析材料
2014/09/30 职场文书
护士年终考核评语
2014/12/31 职场文书
vue数据字典取键值项目的字典问题
2022/04/12 Vue.js
js判断两个数组相等的5种方法
2022/05/06 Javascript