Kmp算法的优势在于它只需要O(m)的与处理时间,而有限状态自动机最快也需要O(m * | Ʃ |)。Kmp算法的主要思路跟字符串自动机很像,在预处理阶段建立一个前缀函数,然后顺序扫描文本T,即可找出所有与模式P相匹配的字符串。前缀函数与字符串自动机中的转移函数功能相同,都是当遇到匹配失败时能根据前缀函数(或者转移函数),利用之前匹配的信息,能够找出下一个应该匹配的位置,避免类似朴素算法做过多的无用功。

图片来自《算法导论》。看图(a),文本T和模式P一直匹配成功前5个字符,但是第6个字符不匹配。但观察可以发现此时已经匹配的5个字符中的后三个是模式P的前三个字符,因此我们可以退而求其次地将已经匹配的字符数减少一点,看能否匹配新的字符。如图(b),此时比较新的字符是否匹配P的第四个字符,这样的比较实际上是把P左移了2位。这个2是这样得来的,原来已经匹配了5位,这5位的后缀中在P的最长前缀(“aba”)的长度是3,5-3=2由此得出应该左移2位。

代码实现

我们先假设已经能够得到前缀函数,即是说先不去管前缀函数是如何计算出的。那当我们已经有方法得到前缀函数后,如何匹配模式P?看下面这段python代码,注意为了方便理解,我在字符串T、P前面都加上了一个空格字符,效果是模拟字符串下标从1开始而不是从0开始。

def kmp_matcher(T, P):T = ' ' + TP = ' ' + Pn = len(T) - 1m = len(P) - 1t = KMP.longest_prefix_suffix(P)q = 0for i in range(1, n+1):while q > 0 and P[q+1] != T[i]:q = t[q]if P[q+1] == T[i]:q += 1if q == m:print i-m+1q = 0

第6行调用函数longest_prefix_suffix,计算出模式P的前缀函数。第8行开始顺序扫描文本T,注意变量q记录此刻与模式P成功匹配的字符的个数。当下一个字符匹配失败时(P[q+1]!=T[i]),q的值根据前缀函数重新计算出,如9、10两行代码。当匹配成功时q的值只需简单加1。最后13行,当q的值(已经匹配的字符数)与模式P的长度相等时,我们便找到了一个匹配的字符串。
是时候来到最难理解的部分了(至少是我认为是最难理解的部分),计算前缀函数。其实如果不嫌慢的话可以暴力解法,但是时间复杂度是O(m^3),太差了。而书本给出的算法是O(m),对比产生美!

首先再说一下前缀函数的意思,前缀函数t[q]的物理意义是模式P的子串P[1..q]的后缀字符串中,是模式P的最大前缀的长度。

def longest_prefix_suffix(P):if P[0] != ' ':P = ' ' + Pm = len(P) - 1t = [0] * (m+1)k = 0match = 0for q in range(2, m+1):while k > 0 and P[k+1] != P[q]:k = t[k]if P[k+1] == P[q]:k += 1t[q] = kreturn t

一些理解

从代码上来看,计算前缀函数和匹配很相似,其实可以把计算前缀函数看作是和自己匹配的过程(书上这么说)。还是一样,为了数组下标从1开始,我把字符串下标0> 的位置放了一个空格。这段代码中变量k记录着当前匹配成功的字符的个数。11、12行代码是好理解的,当下一个字符匹配成功时,简单地把k加1。13行说的是,最后只需在下标为q的位置记录者子串P[1..q]的最长前缀数(k的值)。
对我来说,最难的部分在于理解9、10两行的代码,为什么当不匹配时只需不断的迭代(循环k = t[k]),便能找到适合的k值?

首先,发现对k不断地迭代(即k = t[k]),k的值会越来越小。回忆一下前缀函数的定义,t[q]表示P[1..q]的后缀,同时也是P的前缀的最大长度,所以其值显然要比q小。

所以有不等式:k > t[k] > t[t[k]] > ...

《算法导论》中有句话,通过对前缀函数不断进行迭代,就能列举出P[1..q]的真后缀中的所有前缀P[1..k]。如果真如其所说的话,那么9、10两行代码就好理解了,当匹配失败时,从大至小地列举出其所有前缀,找到一个能使下一个字符匹配成功的前缀即可。而从大到小地列举出所有前缀只需要循环地迭代其前缀函数即可。所以得知,(1)前缀函数不断迭代其值越来越小,(2)而且如书所说可以通过迭代来列举出所有可能的前缀。

python匹配字符串_字符串匹配算法之Kmp算法(Python实现)相关推荐

  1. python 图像变化检测_霍夫变换检测图像直线算法python实现

    创作不易,如果对您有帮助,帮忙点赞哦! 一. 霍夫变换理解: 二. 霍夫变换简介: 霍夫变换,是将坐标由直角坐标系变换到极坐标系,然后再根据数学表达式检测某些形状(如直线和圆)的方法.当 l1直线 上 ...

  2. 字符串的KMP算法--Python实现

    KMP算法Python实现 今天研究KMP算法,看来很多版本,有不同的语言写的,但是感觉越看越乱,最后自己试着写一份进行总结 首先,KMP算法使字符串匹配中的优化算法,使原来的O(m*n)降到了O(m ...

  3. 字符串匹配算法:KMP算法

    KMP (Knuth–Morris–Pratt) 算法是一种改进的字符串匹配算法,它的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的. 题目:给定一个 T 字符串和一个 ...

  4. python 匹配两个字符串的相似度

    python 匹配两个字符串的相似度 用到difflib库,该库是python自带的,不需要在进行下载 用起来很简单,直接放代码: #导入库 from difflib import SequenceM ...

  5. Python灰帽子_黑客与逆向工程师的Python编程之道

    收藏自用 链接:Python灰帽子_黑客与逆向工程师的Python编程之道

  6. 字符串的模式匹配 (朴素模式匹配算法 ,KMP算法)

    字符串的模式匹配 寻找字符串p在字符串t中首次出现的起始位置 字符串的顺序存储 typedef struct {char str[MAXSIZE];int length; }seqstring; 朴素 ...

  7. 字符串匹配算法(KMP算法JAVA版)

    目录 暴力匹配 KMP算法 暴力匹配 暴力算法就是 普通模式的匹配算法 bf算法就是将目标的字符串 的第一个字符与模式的第一个字符进行匹配,相等的话就继续比较第二个字符是否是匹配的,依次进行下去,如果 ...

  8. python Series 添加行_傻傻分不清系列 | Python中各种字符串处理方法

    Python易混淆知识系列:Pandas字符串方法和字符串内建函数,使用Python的一个优势就是字符串处理起来比较容易. Python的初学者在学习字符串内建函数的时候往往会很困惑:字符串的内建函数 ...

  9. 匹配正则_程序员入门基础:python正则表达式贪婪匹配和非贪婪匹配

    此文为python正则表达式的高阶入门,正则基础入门请参考程序员入门基础:python的正则表达式. 一.贪婪匹配和非贪婪匹配 举例说明概念: print('非贪婪匹配',re.search('el+ ...

最新文章

  1. Spring Cloud应用开发(六:使用本地存储方式实现分布式配置管理 )
  2. javascript常用方法函数收集
  3. 超简单的MySQL菜鸟安装教程
  4. oracle 11g安装教程
  5. [知识图谱实战篇] 三.Python提取JSON数据、HTML+D3构建基本可视化布局
  6. Mixing ASP.NET MVC and Webforms
  7. 经典动态规划:0-1 背包问题
  8. vue检测不到data里数组里面元素的变化
  9. matlab 拼接矩阵,Matlab 不同行数矩阵拼接
  10. 华尔街英语学习软件_华尔街英语吧啦吧啦聊点啥:语言学习交流至上
  11. 四大原因告诉你:云为什么比传统IT系统更安全
  12. 根据wsdl文件生成WebService客户端代码
  13. 信息系统高级项目管理师:十大知识领域+五大过程组
  14. Docker镜像的制作、上传、拉取和部署(利用阿里云)
  15. ODC预制光纤连接器
  16. 使用Microsoft Teams Rooms和Teams设备提升混合体验
  17. proteus仿真arduino控制舵机
  18. 【文件包含漏洞-03】文件包含漏洞的利用及如何利用本地文件包含漏洞GetShell
  19. 复制粘贴Excel文件后,显示“安全警告 宏已被禁用”,复制后得到的文件看不到内容
  20. 安卓设置keychain_使用Android KeyChain安全存储对称密钥

热门文章

  1. 冬季防御抗疫情宣传插画素材,时刻提醒大家注意
  2. 手绘平面设计邮票插画素材,复古元素走起
  3. 质量超高的UI素材站!推荐UI\UX设计师
  4. 出错也很美的404页面设计模板
  5. Kernel Livepatching示例
  6. EFLAGS 寄存器,EFLAGS 交叉引用,EFLGAS条件码
  7. 容器(container)技术之发展简史
  8. Just For Fun-用java编个线性回归(一次函数拟合)的图形界面
  9. python安装mysqldb模块_python MysqlDb模块安装及其使用详解
  10. win10+Vmware+centeros10连接xshell和xftp