理解KMP
来源:互联网 发布:js文件怎么打开 编辑:程序博客网 时间:2024/05/21 09:08
初时KMP算法
KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。时间复杂度O(m+n)。
基础前提
1.前缀后缀最长公共元素长度
最长前缀:以第一个字符开始的子串(但是不包括最后一个字符)。
最长后缀:从最后一个字符结束的子串(但是不包括第一个字符)。
最长公共元素就是,前缀与后缀完全匹配时,包含的最多的字符数。
举例:字符串“ababc",其各个子串的最长公共元素长度如下表所示:
字符串
a
b
a
b
c
最大前缀后缀公共元素长度
0
0
1
2
0
比如,对于字符串 "aba"来说,它有长度为1的相同前缀后缀 “a";而对于字符串 "abab"来说,它有长度为2的相同前缀后缀 "ab"2.next数组
next数组考虑的是,除当前字符外的最长相同前缀后缀,所以,可以看出其与最长公共元素长度存在关系。
规则为:将“ababc"对应的最长公共元素长度表的数值,依次向右移动一位,然后赋初值为-1。得到下表:
字符串
a
b
a
b
c
最大前缀后缀公共元素长度
0
0
1
2
0
next数组
-1
0
0
1
2
next数组作用
KMP的next数组,相当于告诉我们,当模式串中的某个字符跟源文本串中的某个字符匹配失败时,模式串下一步应该跳到哪个位置。如模式串中在j处的字符跟文本串在i处的字符不匹配,下一步就用,next[j]处的字符继续跟文本串i处的字符匹配(即j=next[j],相当于模式串向右移动了j-next[j]位)。图示分析如下:
如何求得next数组
基于之前的理解,可知计算next数组最好的方法就是,采用递推形式。
规则如下:其中k和j都是模式串中的两个下标值(k<j),已知求得了next[j]=k,如何就next[j+1]???
1.若p[k] == p[j],则next[j+1] = next[j]+1 = k+1;
2.若p[k] != p[j],如果此时p[next[k]] == p[j],则next[j+1] = next[k]+1;否则,继续递归前缀索引 k=next[k],而后重复此过程。
递归求next数组,代码如下:
void GetNext(char []p, int []next){ int pLen = p.length; next[0] = -1; int k = -1; int j = 0; while(j < pLen-1){ //p[k]表示前缀,p[j]表示后缀 if(k==-1 || p[j]==p[k]){ ++k; ++j; next[j] = k; }else{ k = next[k]; } }}
KMP算法过程
next数组是KMP的核心,上面已经得到了next数组。KMP的规则如下:当前源文本串S匹配到i位置,模式串P匹配到j位置
1.如果j == -1,或者当前字符串匹配成功(即S[i] == P[j]),则令i++,j++,继续匹配下一个字符;
2.如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令i不变,j = next[j]。意味着失配时,模式串P相对于文本串S向右移动了 j-next[j]位(即:失配字符所在位置 - 失配字符对应的next值,且此值大于等于1)。【这里是KMP算法的关键之处,以此避免了失配时,S中字符回溯产生的重复匹配过程】。
KMP代码过程如下:
int Kmp(char []s, char[]p){ int sLen = s.length; int pLen = p.length; int i = 0; int j = 0; while(i<sLen && j<pLen){ if(j==-1 || s[i]==p[j]){//匹配成功 i++; j++; }else{//匹配失败 j = next[j]; } } if(j == pLen) return i-j; else return -1;}
- kmp理解
- kmp理解
- 理解KMP
- KMP理解
- 理解KMP
- KMP算法理解
- 深入理解KMP算法
- KMP算法的理解
- KMP的理解
- 理解KMP算法
- KMP新理解
- KMP算法初步理解
- 我理解之KMP
- 从头到尾理解KMP算法
- 从头到尾理解KMP算法
- KMP算法的理解
- KMP算法理解
- KMP算法---理解
- Linux应用开发--原子操作
- JAVA学习中比较常用的快捷键
- 接口文档写法
- 2017.11.14作业
- springmvc中数据校验
- 理解KMP
- resnet学习资料
- 【我的Java笔记】集合_Set
- 1177三色球
- javaEE 传递到servlet里的 session 与jsp里的不匹配不一致? spring MVC 未解决
- Deep Neural Network
- 软件工程专业导论第三周作业
- 有效集法介绍(Active Set Method)(转)
- Button跳转到指定的方法(onclick)