您的位置:首页 > 其它

扩展kmp算法讲解

2016-02-22 15:53 288 查看
参考文章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;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息