这个next[i]表示的就是最长前后缀,那么头和尾的就不next就可以得出了
那么就剩下判断中间是否存在了,中间的只要不重叠的那部分存在一个next[j]大于的就可以了。
中间的部分是不断扩大的,那么就头尾不断next,中间不断更新新加入的节点即可。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=1e6+9;
char a[maxn];
int next[maxn];
void kmp(char a[],int n)
{
next[0]=0;
next[1]=0;
for(int i=2;i<=n;i++)
{
int t=i-1;
while(t&&a[i]!=a[next[t]+1])
t=next[t];
next[i]=next[t]+(a[i]==a[next[t]+1]);
}
}
int solve(int n)
{
int ans=min(n/3,next[n]);
int l=ans+ans,r=n-ans,ret=0;
for(int i=l;i<=r;i++)
ret=max(ret,next[i]);
while(ans&&ret<ans)
{
ans=next[ans];
ret=max(ret,next[--l]);
ret=max(ret,next[++r]);
}
return ans;
}
int main()
{
// freopen("in.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s",a+1);
kmp(a,strlen(a+1));
int ans=solve(strlen(a+1));
cout<<ans<<endl;
}
return 0;
}