字符串匹配算法(三)-KMP算法
今天我们来聊一下字符串匹配算法里最著名的算法-KMP算法,KMP算法的全称是 Knuth Morris Pratt 算法,是根据三位作者(D.E.Knuth,J.H.Morris 和 V.R.Pratt)的名字来命名的。KMP算法和BM的算法思想类似,如果对BM算法不熟悉的同学可以看这篇文章BM算法详解。
KMP算法原理
KMP的算法核心思想是,当模式串b和主串a在进行匹配的时候,如果遇到不匹配的字符,我们希望找到一种规律,可以使得模式串b多向后滑动几位,跳过那些肯定不匹配的情况。
首先我们先明确二个定义:在模式串和主串匹配的过程中,我们把不能匹配的字符叫做坏字符,把已经匹配的那段字符叫做好前缀。在模式串和主串匹配的过程中,当遇到坏字符后,对于已经比对过的好前缀,能否找到一种规律,将模式串可以滑动多位呢。
其实我们只需要拿好前缀本身,在他的后缀子串中,查找最长的那个可以跟好前缀的前缀子串匹配的。假设最长可匹配的那部分前缀子串是{u},长度是k。我们可以把模式串一次性先后滑动j-k位,即当匹配到坏字符时,我们把j更新为k,然后i不变,然后再继续匹配。
下面我们再明确两个定义,我们把好前缀的所有后缀子串中,最长的可以匹配前缀子串的那个后缀称为最长可匹配后缀子串,对应的前缀子串叫做最长可匹配前缀子串。那如何来求好前缀的最长可匹配前缀和后缀子串呢?
KMP算法是通过构建了一个数组来求的。该数组的下标是每个前缀结尾字符下标,该数组的值是这个前缀的最长可以匹配前缀子串的结尾字符下标。我们把这个数组定义为 next 数组,同时也可以称为是失效函数。如下图所示。
next数组的计算方法
我们来思考这么一个问题。如果next[i-1]=k-1,也就是说子串b[0, k-1]是b[0, i-1]的最长可匹配前缀子串。如果子串 b[0, k-1]的下一个字符 b[k],与 b[0, i-1]的下一个字符 b[i]匹配,那么子串 b[0, k]就是 b[0, i]的最长可匹配前缀子串。所以,next[i]等于 k。如果 b[0, k-1]的下一字符 b[k]跟 b[0, i-1]的下一个字符 b[i]不相等呢?那我们这个时候就不能简单地通过 next[i-1]得到 next[i]了。这个时候该怎么办呢?我们假设 b[0, i]的最长可匹配后缀子串是 b[r, i]。如果我们把最后一个字符去掉,那 b[r, i-1]肯定是 b[0, i-1]的可匹配后缀子串,但不一定是最长可匹配后缀子串。所以,既然 b[0, i-1]最长可匹配后缀子串对应的模式串的前缀子串的下一个字符并不等于 b[i],那么我们就可以考察 b[0, i-1]的次长可匹配后缀子串 b[x, i-1]对应的可匹配前缀子串 b[0, i-1-x]的下一个字符 b[i-x]是否等于 b[i]。如果等于,那 b[x, i]就是 b[0, i]的最长可匹配后缀子串。可是,如何求得 b[0, i-1]的次长可匹配后缀子串呢?次长可匹配后缀子串肯定被包含在最长可匹配后缀子串中,而最长可匹配后缀子串又对应最长可匹配前缀子串 b[0, y]。于是,查找 b[0, i-1]的次长可匹配后缀子串,这个问题就变成,查找 b[0, y]的最长匹配后缀子串的问题了。按照这个思路,我们可以考察完所有的 b[0, i-1]的可匹配后缀子串 b[y, i-1],直到找到一个可匹配的后缀子串,它对应的前缀子串的下一个字符等于 b[i],那这个 b[y, i]就是 b[0, i]的最长可匹配后缀子串。这块比较绕,可以先看代码,然后反过来多读几遍。
#b表示模式串
#m表示模式串的长度
def getNext(b,m):
next=[-1]*m
k=-1
for i in range(1,m):
while k!=-1 and b[k+1]!=b[i]:
k=next[k]
if b[k+1]==b[i]:
k=k+1
next[i]=k
return next
我们有了next数组后,就可以动手来实现kmp算法了。
#b表示模式串
#m表示模式串的长度
def getNext(b,m):
next=[-1]*m
k=-1
for i in range(1,m):
while k!=-1 and b[k+1]!=b[i]:
k=next[k]
if b[k+1]==b[i]:
k=k+1 next[i]=k
return next def kmp(a,n,b,m):
next=getNext(b,m)
print(next)
j=0
for i in range(n):
while j>0 and a[i]!=b[j]:
j=next[j-1]+1 if(a[i]==b[j]):
j=j+1 #找到匹配模式串的了
if(j==m):
return i-m+1 return -1
到此为止,我们的kmp算法就学完了。更多硬核知识,请关注公众号。
字符串匹配算法(三)-KMP算法的更多相关文章
- 字符串匹配算法之 kmp算法 (python版)
字符串匹配算法之 kmp算法 (python版) 1.什么是KMP算法 KMP是三位大牛:D.E.Knuth.J.H.MorriT和V.R.Pratt同时发现的.其中第一位就是<计算机程序设计艺 ...
- 动画演示Sunday字符串匹配算法——比KMP算法快七倍!极易理解!
前言 上一篇我用动画的方式向大家详细说明了KMP算法(没看过的同学可以回去看看). 这次我依旧采用动画的方式向大家介绍另一个你用一次就会爱上的字符串匹配算法:Sunday算法,希望能收获你的点赞关注收 ...
- 字符串匹配算法之kmp算法
kmp算法是一种效率非常高的字符串匹配算法,是由Knuth,Morris,Pratt共同提出的模式匹配算法,所以简称KMP算法 算法思想 在一个字符串中查找另一个字符串时,会遇到如下图的情况 我们通常 ...
- Python 细聊从暴力(BF)字符串匹配算法到 KMP 算法之间的精妙变化
1. 字符串匹配算法 所谓字符串匹配算法,简单地说就是在一个目标字符串中查找是否存在另一个模式字符串.如在字符串 "ABCDEFG" 中查找是否存在 "EF" ...
- 字符串匹配算法之————KMP算法
上一篇中讲到暴力法字符串匹配算法,但是暴力法明显存在这样一个问题:一次只移动一个字符.但实际上,针对不同的匹配情况,每次移动的间隔可以更大,没有必要每次只是移动一位: 关于KMP算法的描述,推荐一篇博 ...
- 数据结构学习之字符串匹配算法(BF||KMP)
数据结构学习之字符串匹配算法(BF||KMP) 0x1 实验目的 通过实验深入了解字符串常用的匹配算法(BF暴力匹配.KMP.优化KMP算法)思想. 0x2 实验要求 编写出BF暴力匹配.KM ...
- 字符串匹配算法之Sunday算法(转)
字符串匹配算法之Sunday算法 背景 我们第一次接触字符串匹配,想到的肯定是直接用2个循环来遍历,这样代码虽然简单,但时间复杂度却是Ω(m*n),也就是达到了字符串匹配效率的下限.于是后来人经过研究 ...
- 字符串匹配算法之BM算法
BM算法,全称是Boyer-Moore算法,1977年,德克萨斯大学的Robert S. Boyer教授和J Strother Moore教授发明了一种新的字符串匹配算法. BM算法定义了两个规则: ...
- 数据结构4_java---顺序串,字符串匹配算法(BF算法,KMP算法)
1.顺序串 实现的操作有: 构造串 判断空串 返回串的长度 返回位序号为i的字符 将串的长度扩充为newCapacity 返回从begin到end-1的子串 在第i个字符之前插入字串str 删除子串 ...
随机推荐
- 玩转html2canvas以及常见问题解决
前端小伙伴经常会遇到页面截图或者把网页中指定的区域(某个大div)的内容转换成png的图片.这个时候常常会用到html2canvas库来实现,js真的很强大. 我最近也遇到了一个需求,需要把输入的文本 ...
- 数学:3D和矩阵
跟紧工作需求学习,于是抽了点时间看了看用于2D3D转换的矩阵内容. 矩阵在3D数学中,可以用来描述两个坐标系间 的关系,通过定义的运算能够把一个坐标系中的向量转换到另一个坐标系中.在线性代数中,矩阵就 ...
- Vue 消除Token过期时刷新页面的重复提示
1.问题现象 页面长时间未操作,再刷新页面时,第一次弹出"token失效,请重新登录!"提示,然后跳转到登录页面,接下来又弹出了n个"Token已过期"的后 ...
- MyBatis:MyBatis-Plus条件构造器EntityWrapper
EntityWrapper 简介 1. MybatisPlus 通过 EntityWrapper(简称 EW,MybatisPlus 封装的一个查询条件构造器)或者 Condition(与 EW 类似 ...
- 码云使用svn无法提交空文件夹
错误信息: svn: E200015: Commit failed (details follow): svn: E200015: Empty directories is not supported ...
- Springboot:单元测试Junit基本注解@BeforeClass、@AfterClass、@Before、@After、@Test、
一.unit中集中基本注解,是必须掌握的. @BeforeClass – 表示在类中的任意public static void方法执行之前执行 @AfterClass – 表示在类中的任意public ...
- 想成为Java高手的25个学习目标
本文将告诉你学习Java需要达到的25个目标,希望能够对你的学习及找工作有所帮助.对比一下自己,你已经掌握了这25条中的多少条了呢? 1.你需要精通面向对象分析与设计(OOA/OOD).涉及模式(GO ...
- 转:nginx服务器配置
1. user www-data说明的是使用的用户,至于www-data这个用户是系统自带的,我们不用说系统里没有这个账户的,虽然这个账户具体是做什么的,我也不太清楚2.worker_processe ...
- 你会用哪些JavaScript循环遍历
总结JavaScript中的循环遍历定义一个数组和对象 const arr = ['a', 'b', 'c', 'd', 'e', 'f']; const obj = { a: 1, b: 2, c: ...
- 2019年最新android常用开源库汇总上篇(转)
1.基本控件 1.1.TextView ScrollNumber ReadMoreTextView HtmlImage android-autofittextview html-textview Ba ...