前缀和后缀的求法,自然会想到扩展的KMP,但是KMP也是可以的。同样,这题两个方法都行。
(1)用KMP求next函数,当next[len]>len2 (len为len1+len2),在求next[len]的前一个next,即next[next[len]],直到小于等于len2.
(2)扩展的KMP就是求出extand值,找到其中最大的extand[i]值,使其满足extand[i]==len-i;
我是用扩展的KMP做的,其实应该没有前一个快,但是习惯了,对这道题来说,足够快了。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 50010
using namespace std;
char s[N],t[N];//s是主串,t是待判断的子串
int next[N],extand[N];
void getnext(char *T){// next[i]: 以第i位置开始的子串 与 T的公共前缀
int i,length = strlen(T);
next[0] = length;
for(i = 0;i<length-1 && T[i]==T[i+1]; i++);
next[1] = i;
int a = 1;
for(int k = 2; k < length; k++){
int p = a+next[a]-1, L = next[k-a];
if( (k-1)+L >= p ){
int j = (p-k+1)>0? (p-k+1) : 0;
while(k+j<length && T[k+j]==T[j]) j++;// 枚举(p+1,length) 与(p-k+1,length) 区间比较
next[k] = j, a = k;
}
else next[k] = L;
}
}
void getextand(char *S,char *T){
memset(next,0,sizeof(next));
getnext(T);
int Slen = strlen(S), Tlen = strlen(T), a = 0;
int MinLen = Slen>Tlen?Tlen:Slen;
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-1)+L >= p ){
int j = (p-k+1)>0? (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()
{
int i,j;
while(scanf("%s%s",s,t)!=EOF)
{
getextand(t,s);
int MIN=0;
int len=strlen(t);
for(i=0;i<len;i++)
{
if(extand[i]==(len-i)&&MIN<extand[i]) MIN=extand[i];
}
if(MIN==0) printf("0\n");
else
{
for(i=0;i<MIN;i++)
printf("%c",s[i]);
printf(" %d\n",MIN);
}
}
return 0;
}