扩张kmp算法
扩展kmp算法
扩展KMP算法
什么是扩展KMP?
- 扩展kmp是求模式串和主串的每一个后缀的最长公共前缀长度。
- 扩展KMP算法是利用前面的已知条件减少多余匹配,达到缩短时间的算法。
- 扩展KMP算法目的是得到next数组和extend数组。
- next[ i ] 表示的是从自己的第i位开始,模式串T与自己匹配的字符个数。
- extend[ i ] 表示的是从主串S的第i位开始,模式串T与主串S匹配的字符个数。
扩展KMP算法的思路:
-
先介绍几个比较重要的参数:
- a :当前求next值或者extend值时使得p最大时的位置。
-
p:当前比较过的最大位置。p=a+next[ a ]-1或者p=a+extend [ a ]-1。这个式子不难理解吧。
- l :是利用模式串T的自相似性求出的当前第i位的的最长公共前缀长度,但是并不一定等于实际的最长公共前缀长度。这只是根据已经匹配过得数据得出的结论,后没有匹配过得地方谁也说不定。也许没匹配过得地方也相同呢。
- 也就是说extend[ i ]>=l,或者next[ i ]>=l。
- l=next[ i-a ]。注意无论是求next 还是extend 都是同一个式子。
-
求next数组:
- next [ 0 ]等于字符串T的长度。
- 通过逐个比较的方法求出next [ 1 ]。
- 然后逐个求第2~n的next值。
- 判断l+i-1>=p是否成立。即判断通过模式串自相似性求出的最长公共子串是否超过已经比较过的最大位置。
- 若成立,继续向后方没有比较过的位置比较,若匹配自加1,直到不匹配为止此时的值即为next[ i ]的值。
- 若不成立,next [ i ]=l 。
-
求extend数组:
- 通过逐个比较求出extend[ 0 ]。
- 然后逐个求第1~n的extend值。
- 判断l+i-1>=p是否成立。即判断通过模式串自相似性求出的最长公共子串是否超过已经比较过的最大位置。
- 若成立,继续向后方没有比较过的位置比较,若匹配自加1,直到不匹配为止此时的值即为extend[ i ]的值。
- 若不成立,extend[ i ]=l 。
扩展KMP代码:
<span style="font-size:18px;">#include<stdio.h> #include<string.h> using namespace std; int extend[100001],next[100001]; void exkmp(char *s,char *t) { int slen,tlen,a=0,i,l,p,j; slen=strlen(s); tlen=strlen(t); next[0]=tlen;//求next数组 while(a<tlen-1 && t[a]==t[a+1])a++; next[1]=a; a=1; for(i=2;i<tlen;i++) { p=a+next[a]-1; l=next[i-a]; if(i+l-1>=p) { j=(p-i+1)>0?p-i+1:0; while(i+j<tlen && t[i+j]==t[j])j++; next[i]=j; a=i; } else next[i]=l; }//求extend数组 a=0; while(a<tlen && a<slen && t[a]==s[a])a++; extend[0]=a; a=0; for(i=1;i<slen;i++) { p=a+extend[a]-1; l=next[i-a]; if(i+l-1>=p) { j=(p-i+1)>0?p-i+1:0; while(i+j<slen && j<tlen && s[i+j]==t[j])j++; extend[i]=j; a=i; } else extend[i]=l; } } int main() { //具体情况具体分析。 return 0; }</span>
版权声明:本文为博主原创文章,未经博主允许不得转载。