题意:
给出一个长度为n的串S,求满足下面条件的最大的L:
- L<=n/2
- S的L前缀和S的L后缀是循环同构的。
思路:
设前缀为aaa,后缀为bbb,如果a,ba,ba,b循环同构,那么a,ba,ba,b是由一个字符串加上两个borderborderborder形成的。
即如下图所示:
s1,i=sl+1,n,si+1,j=sk,ls_{1,i}=s_{l+1,n},s_{i+1,j}=s_{k,l}s1,i=sl+1,n,si+1,j=sk,l
于是考虑枚举可行的iii,并对于每个iii求出满足条件的最大的jjj。
我们设fi=jf_i=jfi=j。
那么可以得出一个结论:fi≤fi+1+2f_i\le f_{i+1}+2fi≤fi+1+2 (证明显然)
然后就暴力枚举jjj即可,摊下来复杂度O(n)O(n)O(n)。
代码:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int N=1e6+5;
char s[N];
int n,f[N];
typedef unsigned long long Ull;
typedef long long ll;
const Ull bas=141;
const int mod=1e9+9;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
struct string_hash{
Ull pw[N],ss[N];
int pww[N],sss[N];
inline void init(){
pw[0]=pww[0]=1;
for(ri i=1;i<=n;++i)pw[i]=pw[i-1]*bas,pww[i]=mul(pww[i-1],bas);
for(ri i=1;i<=n;++i)ss[i]=ss[i-1]*bas+(s[i]-'0'+15),sss[i]=add(mul(sss[i-1],bas),s[i]-'0'+15);
}
inline Ull gethash1(int l,int r){return ss[r]-ss[l-1]*pw[r-l+1];}
inline int gethash2(int l,int r){return dec(sss[r],mul(sss[l-1],pww[r-l+1]));}
inline bool check(int l1,int r1,int l2,int r2){return gethash1(l1,r1)==gethash1(l2,r2)&&gethash2(l1,r1)==gethash2(l2,r2);}
}S;
int main(){
scanf("%d%s",&n,s+1);
S.init();
f[n>>1]=0;
int ans=0;
for(ri l1,r1,l2,r2,i=(n>>1)-1;~i;--i){
l1=i+1,r2=n-i;
for(r1=min(n>>1,i+1+f[i+1]+1),l2=n+1-r1;r1>=l1;--r1,++l2)if(S.check(l1,r1,l2,r2))break;
f[i]=r1-l1+1;
if(S.check(1,i,n-i+1,n))ans=max(ans,i+f[i]);
}
cout<<ans;
return 0;
}