题目大意:求最长的子串E,它既是串s的前缀又是后缀,还在串s的中间出现过(不能重叠)。
直接从fai[len]开始枚举,在中间进行匹配,成功即可输出。
#include <cstdio>
#include <cstring>
#define N 1000010
int tst,fail[N],m;
char s[N];
inline void getfail(){
int k=0;fail[1]=0;
for(int i=2;i<=m;++i){
while(k&&s[k+1]!=s[i]) k=fail[k];
if(s[k+1]==s[i]) ++k;
fail[i]=k;
}
}
inline bool kmp(char *ss,char *t,int n,int mm){
int k=0;
for(int i=1;i<=n;++i){
while(k&&t[k+1]!=ss[i]) k=fail[k];
if(t[k+1]==ss[i]) ++k;
if(k==mm) return true;
}
return false;
}
int main(){
// freopen("a.in","r",stdin);
scanf("%d",&tst);
while(tst--){
scanf("%s",s+1);m=strlen(s+1);
getfail();int k=fail[m];
for(;k;k=fail[k]){
if(kmp(s+k,s,m-k*2,k)) break;
}
printf("%d\n",k);
}
return 0;
}