KMP字符串匹配
来源:互联网 发布:穿越时光的地铁知乎 编辑:程序博客网 时间:2024/06/06 04:03
我们假设有上图字符串S:abcaab和T:abcababcaabab字符匹配需求,左边是朴素算法:即从T的第0位和分别和S的1~n位开始比较,相同则用黄色标注,不同则用红色标注,如果遇到不同,然后T的第0位和下一位开始重新来过开始第二轮比较。但是,在这个比较的过程中,我们会发现两种情况:
1. 0~3位分别相同,即T[0]=S[0],T[1]=S[1],T[2]=S[2],T[3]=S[3],同时T[0]!=T[1]!=T[2],所以显然T[0]!=S[1]!=S[2],所以显然T[0]和S[1],S[2]的比较是没有必要的,所以对于KMP来说,第二轮和第三轮的比较的次数是都是0!
2. 然后,我们再看第四轮比较,我们同时发现,由于abca,前一位和后一位是相同的,所以当开始第三轮的时候,T[0]=S[3],这次比较也是多余的,直接比较T[1]?=S[4],发现相等,T[2]?=T[5],发现不等,跳到下一轮。
这两种情况所带来的效果就是:本来遇到不匹配的位置T[j]!=S[i]时是应该“回溯”到T[0],用T[0]与上次和T[0]比较的S[n]下一位S[n+1]开始比较的,可是由于T串自身的一些特点,使得T不用“回溯”到T[0],而是“回溯”到T[j],然后继续和S[i]比较,所以问题来了:这个位置j到底是如何规定的?
“回溯”是KMP算法的的关键所在,求出回溯点j也就是找到了KMP的核心所在。
当T[4]!=S[4]时,由于第一种情况,所以首先T[0]不必和S[2],S[3]相比,又由于第二种情况,所以不必回溯到T[0],而只需回溯到T[1]?=T[4]。所以第一种情况决定了S[i]不用回溯到S[n+1],第二种情况决定了T[j]不用回溯到T[0],而这个T[1]中的j=1,就是出现不匹配的时j位置之前,即T[0]~T[j-1]有多少相同的前后缀,例如我们假设是在T[5]的时候出现的不匹配T[5]!=S[5],则下一轮比较,只需比较T[2]?=T[5],这个2就是T[0]~T[4]之间有两个前后缀相同!所以我们要做的就是对于T,求出每一个位置之前有多少相同的前后缀:
首先:规定T[0]=-1,T[1]由于1位置之前只有一个元素,所以T[1]=0
然后:每有一个后缀和前缀元素相同,假设此时后缀位置为i,则T[i+1]回溯值为此时回溯值加1,同时开始比较i+1和j+1,我们通常把next[i]称为回溯的位置值。实际上此时n位前缀和n位后缀也处于上述S和T的比较过程中,例如对于ababaaaba:
在T[5]时,因为T[0~2]=T[2~4],求出next[5]=3时,接下来要求next[6],即比较(T[3]=b) ?= (T[5]=a),此时显然不同!那我们接下来要做什么逻辑呢来判断next[6]呢?
此时,next[5]的求解处于上图中的位置,由文章起始讲的“回溯”可知,接下来要比较的是T[j=1]?=T[j=5],发现不等,则比较T[j=0]?=T[j=5],然后相等,则认为next[6]=j+1=1,然后依次类推求解接下来的值!在这个过程中j=3—>j=1—>j=0,也是回溯的问题,而此时回溯点已经在之前求出来了!
说了这么久,我们来看看实际的代码是怎样的!
对于next值:
对于匹配函数:
- KMP 字符串匹配算法
- kmp字符串匹配算法
- kmp字符串匹配算法
- KMP字符串匹配算法
- 字符串匹配算法-kmp
- KMP(字符串匹配)算法
- 字符串匹配 KMP
- KMP 字符串匹配算法
- 字符串匹配算法:KMP
- KMP算法 字符串匹配
- 字符串匹配 KMP 算法
- KMP字符串匹配(1)
- KMP字符串匹配(2)
- KMP字符串匹配(3)
- KMP字符串匹配算法
- KMP字符串匹配
- KMP字符串匹配算法
- KMP字符串匹配
- 5-12 两个数的简单计算器 (10分)
- 无序整形数组,如何找到最长连续序列长度,时间复杂度O(n)
- Maven
- 设计模式-创建型软件设计模式(三)
- Stereo match 基本原理介绍
- KMP字符串匹配
- Python 将模块作为脚本来执行
- 记一次失败的oracle安装过程
- AsyncTash基础创建规则与例子
- gcc和g++的区别
- BOZJ 2301: [HAOI2011]Problem b 莫比乌斯反演
- 51nod 1267 4个数和为0
- finally究竟什么时候执行
- Python数据结构--字典