http://acm.hdu.edu.cn/showproblem.php?pid=4763
数据水 当初n^2都能过
将所给串所有公共前缀后缀长度都找出来 然后二分长度 看中间剩下的那部分是否包含二分的这个公共前缀后缀
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int nxtt[maxn],nxts[maxn],len[maxn];
char ch[maxn],s[maxn],t[maxn];
int n,tot;
void kmp(char *t,int lt)
{
int i,j;
nxtt[0]=-1;
i=0,j=-1;
while(i<lt)
{
if(j==-1||t[i]==t[j])
{
i++,j++;
nxtt[i]=j;
}
else j=nxtt[j];
}
}
bool solveII(char *s,int ls,char *t,int lt)
{
int i,j;
i=0,j=0;
while(i<ls)
{
if(j==-1||s[i]==t[j])
{
i++,j++;
nxts[i]=j;
if(j==lt) return 1;
}
else j=nxtt[j];
}
return 0;
}
bool solveI(int p)
{
int i;
if(3*p>n) return 0;
for(i=0;i<p;i++) t[i]=ch[i];
for(i=p;i<n-p;i++) s[i-p]=ch[i];
kmp(t,p);
return solveII(s,n-2*p,t,p);
}
int main()
{
int t,i,l,r,m,ans;
scanf("%d",&t);
while(t--)
{
scanf("%s",ch);
n=strlen(ch);
kmp(ch,n);
i=nxtt[n],tot=0;
while(i!=0)
{
len[++tot]=i;
i=nxtt[i];
}
l=1,r=tot;
while(l<r) swap(len[l++],len[r--]);
l=1,r=tot,ans=0;
while(l<=r)
{
m=(l+r)/2;
if(solveI(len[m])) l=m+1,ans=len[m];
else r=m-1;
}
printf("%d\n",ans);
}
return 0;
}
/*
1
aaaaaaaaaa
*/