​

扩展Kmp_最长公共前缀



 //扩展 KMP 算法 (2018.2.21)
/*
S |_______|____________________|______|_________|
0 a i p Slen-1

T |______|_____________|______|_______|
0 p-i i-a p-a Tlen-1
nxt[i-a]?

设 S[a, p) 与 T[0, p - a) 匹配,
则当 S[p] != T[p - a] 时, 若
1) i + nxt[i - a] < p, 则 lcp[i] = nxt[i - a]
2) i + nxt[i - a] == p, 则从 S[p] 和 T[p - i] 开始往后暴力比较
3) i + nxt[i - a] > p, 则 lcp[i] = p - i
*/
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;

char S[1000005], T[1000005];
int Slen, Tlen, nxt[1000005], lcp[1000005];

int main(){
while(scanf("%s%s", S, T) != EOF){
Slen = strlen(S), Tlen = strlen(T);
nxt[0] = Tlen;
for(register int i = 1, a = 0, p = 0; i < Tlen; i++)
{
if(i + nxt[i - a] >= p)
{
if(i > p)
//有可能输入的两个字符串完全不相等,那p的值就要等于i
//也就是说始终间将第一个字符串的第i个字符与第二个字符串的第一个字符开始比
//p代表从前比较时,最靠左的失效位置, 在我们的讨论中一直认为i<p,所以当i>p时,p=i
//于是从从前的失效位置开始比较,即从t[p]开始与t[p-i]开始比较,
p = i;
while(p < Tlen && T[p] == T[p - i]) p++;
nxt[i] = p - i, a = i;
}
else nxt[i] = nxt[i - a];
}
for(register int i = 0, a = 0, p = 0; i < Slen; i++){
if(i + nxt[i - a] >= p){
if(i > p) p = i;
while(p < Slen && S[p] == T[p - i]) p++;
lcp[i] = p - i, a = i;
}
else lcp[i] = nxt[i - a];
}
for(register int i = 0; i < Slen - 1; i++) printf("%d ", lcp[i]);
printf("%d\n", lcp[Slen - 1]);
}
return 0;
}


  

 

 

 



#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

const int maxn=9999;

int Next[maxn];
int extand[maxn]; //s的后缀与t的最长公共前缀。

void getnext(char* t)
{
int i,len=strlen(t);
Next[0]=len;
for(i=0;i<len-1&&t[i]==t[i+1];i++);
Next[1]=i;
int a=1;
for(int k=2;k<len;k++){
int p=a+Next[a]-1,l=Next[k-a];
if(k+l-1>=p){ //l>=p-k+1
int j=max(p-k+1,0);
while(k+j<len&&t[k+j]==t[j]) j++;
Next[k]=j;a=k;
}else Next[k]=l;
}
}

void getextend(char* s,char* t)
{
memset(Next,0,sizeof(Next));
getnext(t);
int slen=strlen(s),tlen=strlen(t),a=0;
int minlen=min(slen,tlen);
while(a<minlen&&s[a]==t[a]) a++;
extand[0]=a,a=0;
for(int k=1;k<slen;k++){
int p=a+extand[a]-1,l=Next[k-a];
if(k+l-1>=p){
int j=max(p-k+1,0);
while(k+j<slen&&j<tlen&&s[k+j]==t[j]) j++;
extand[k]=j;a=k;
}else extand[k]=l;
}
}

int main()
{
char s[maxn],t[maxn];
while(scanf("%s%s",s,t)!=EOF){
getextend(s,t);

for(int i=0,len=strlen(t);i<len;i++)
printf("%d ",Next[i]);
puts("");
for(int i=0,len=strlen(s);i<len;i++)
printf("%d ",extand[i]);
puts("");
}
}