扩展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>