参考文章http://www.cnblogs.com/10jschen/archive/2012/09/03/2668149.html
一.扩展kmp得到的是什么
字符串A,B。B是模式串(子串)。求解A[i ……lenA -1]与B的最长公共前缀,记录在数组ex[i]中
二.算法实现
分为两步,第一步是对B模式串进行处理也是求B[i,Blen - 1]与B的最长公共前缀,用next数组存储,第二部是将A与B进行匹配,其实他们的方法是一样的
我们先对第二步进行分析
首先假设B的nexta[]的值已经全部求出,且i之前全部的ex值也已经求出,再设p为匹配过程中的最大位置,设k为达到最大位置时的起始位置,由此可知p = k + ex[k] - 1
由ex的定义可知:A[k……k + ex[k] -1] 与B[0……ex[k] - 1]相等 显然i > k 所以 A[i……k + ex[k] - 1]
与 B[i - k……ex[k]-1] 匹配,设L = nexta[i - k],根据nexta的定义有B[0……L-1] = B[i-k……i - k + L - 1]
只需判断ex[k] - 1(=p - k ) 与 i - k + L - 1那个大
1.i - k + L - 1 < p - k 及 p > i + L - 1,p >= i + L
由 A[i……p] 与 B[i - k……p-k] 匹配得到A[i……L + i - 1]与B[i - k……i - k + L - 1] ,又有B[0……L-1] = B[i-k……i - k + L - 1]。故A[i……L + i - 1] = B[0……L-1] 可知ex[i] >= L,如果ex[i] > L则A[i……L + i ] = B[0……L] .因为p = k + ex[k] - 1 >= i + L,所以A[i……L + i] = B[i - k……i - k + L],推出B[0……L] = k + ex[k] - 1与next数组定义不符合。所以ex[i] = L
2.i - k + L - 1 >= p - k 及 p <= i + L - 1,p < i + L
A[i……p] = B[i - k……p-k]
B[0……L-1] = B[i-k……i - k + L - 1] 所以B[0……p -i] = B[i-k……p - k]
所以A[i……p] = B[0……p -i],p是匹配到的最远的地方,需要继续从A[p + 1] 和 B[p - i + 1]开始继续匹配
设j = p - i + 1,则 p + 1 = i + j。p增加了,所以要更新p和k的值
ps:注意j如果是小于零的就让j = 0,从B的最前端开始匹配
第一步显然和第二步的方法是一样的,注意第一步中都是nexta数组
对于B来说nexta[0] 肯定等于n,然后求出nexta[1]的最远距离,另k = 1,不用对p赋值
对于AB匹配来说,要遍历求出extend[0],遍历应该到两个字符串中长度较短的一个就停止。并另k = 0。
代码如下
//需定义extend 和 nexta
void EKMP(char s[],char t[])//s主串,t模式串
{
memset(nexta,0,sizeof(nexta));
memset(extend,0,sizeof(extend));
int slen = strlen(s),tlen = strlen(t);
int len = min(slen,tlen);
nexta[0] = tlen;
int k;
for(k = 0;k + 1 < tlen && t[k] == t[k + 1];k ++ )
{
}
nexta[1] = k;
k = 1;
int p,L,j;
for(int i = 2; i < tlen; i ++)
{
p = k + nexta[k] - 1, L = nexta[i - k];
if(i + L <= p)
{
nexta[i] = L;
}
else
{
j = p - i + 1;
if(j < 0)
j = 0;
while(i + j < tlen && t[i + j] == t[j])
{
j++;
}
nexta[i] = j;
k = i;
}
}
for(k = 0;k < len && s[k] == t[k];k ++ )
{
}
extend[0] = k;
k = 0;
for(int i = 1; i < slen; i ++)
{
p = k + extend[k] - 1, L = nexta[i - k];//注意p是加extend
if(i + L <= p)
{
extend[i] = L;
}
else
{
int j = p - i + 1;
if(j < 0)
j = 0;
while(i + j < slen &&j < tlen && s[i + j] == t[j])
{
j++;
}
extend[i] = j;
k = i;
}
}
}