*算法介绍:
扩展KMP算法是对KMP算法的一种扩展,对于求两个字符串的公共部分非常有效。题目可以有多种变化。最普通的的是给定母串text与子串part。求数组extend[i],extend[i]表示text[i...n]字符串与part最长前缀的长度。
与KMP的思路一致,我们设next数组表示:next[i...n]与next数组本身的最长公共前缀长度。
假设我们现在已经知道extend[0....i]的值,接下来要求extend[i+1]的值。设1<=k<=i,且使k+extend[k]最大(这意味着以text[k]为前缀匹配时,在text字符串中匹配达到最远)。
根据next数组的意义可以知道以part[i-k]为前缀与part数组的前缀匹配时,匹配长度L=next[i-k]。我们至少可以知道text[i...k+extend[k]-1]与part[0...next[i-k]-1]匹配,长度为L。
(1)若:L+i
(2)若:L+i>=k+extend[k] 我们目前只能确定(1)中的L个字符匹配,接下来不能确定,所以需要挨个比较,并且比较完后需令:k=i+1。
与KMP数组的next数组获取思路相同,将以上算法对part字符串自身使用,即可得到。思路分析时只需将上述思路分析中的text字符串替换为part字符串本身,将extend数组替换为next数组即可求得。
*思路:
1.主代码:
据extend[k]得:
text[k...k+extend[k]-1]=part[0...extend[k]-1]
所以可以推知:
text[i...k+extend[k]-1]=part[i-k...extend[k]-1]
2.next数组的获取:
*代码:
#include<iostream>
#include<cstring>
using namespace std;
int next[1000],lent,lenp,extend[1000];
char text[1000],part[1000];
void get_next()
{
int j=0,i=0,p,l,k;
next[0]=lenp;
while(j<lenp&&part[j]==part[j+1])
j++;
next[1]=j;
k=1;
for(i=2;i<lenp;i++)
{
p=next[k]+k-1,l=next[i-k];
if(l+i-1<p)
next[i]=l;
else
{
j=max(0,p+1-i);
while(i+j<lenp&&part[j]==part[i+j])
j++;
next[i]=j;
k=i;
}
}
}
int extend_KMP()
{
int i,j=0,l,k=0,p;
get_next();
while(j<lent&&j<lenp&&part[j]==text[j])
j++;
extend[0]=j;
for(i=1;i<lent;i++)
{
l=next[i-k];
p=extend[k]+k-1;
if(l+i-1<p)
extend[i]=l;
else
{
j=max(0,p+1-i);
while(j+i<lent&&part[j]==text[i+j])
j++;
extend[i]=j;
k=i;
}
}
}
int main()
{
int i;
cin>>part>>text;
lenp=strlen(part);
lent=strlen(text);
extend_KMP();
for(i=0;i<lenp;i++)
cout<<next[i];
cout<<endl;
for(i=0;i<lent;i++)
cout<<extend[i];
return 0;
}