【BZOJ2803】【POI2012】—Prefixuffix(哈希)
考虑循环同构一定可以表示成这样的
考虑枚举的长度
就变成了求子区间最长相同前后缀
假设当前
显然有
也就是说如果从大到小枚举最长前后缀最多变大
暴力做就可以了
数据有点强,我的自然溢出双哈希都被卡了
写了取模才过了
#include<bits/stdc++.h>
using namespace std;
#define gc getchar
inline int read(){
char ch=gc();
int res=0,f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
#define ll long long
#define pb push_back
#define pii pair<int,int>
#define fi first
#define se second
const ll bas1=131,bas2=97;
const ll mod1=19260817,mod2=19491001;
const int N=1000005;
ll p1[N],p2[N],s1[N],s2[N];
int n;
char s[N];
inline bool has1(int l1,int r1,int l2,int r2){
return ((s1[r1]-s1[l1-1]*p1[r1-l1+1])%mod1+mod1)%mod1==((s1[r2]-s1[l2-1]*p1[r2-l2+1])%mod1+mod1)%mod1;
}
inline bool has2(int l1,int r1,int l2,int r2){
return ((s2[r1]-s2[l1-1]*p2[r1-l1+1])%mod2+mod2)%mod2==((s2[r2]-s2[l2-1]*p2[r2-l2+1])%mod2+mod2)%mod2;
}
inline bool check(int l1,int r1,int l2,int r2){
return has1(l1,r1,l2,r2)&&has2(l1,r1,l2,r2);
}
int main(){
#ifdef Stargazer
freopen("lx.cpp","r",stdin);
#endif
p1[0]=p2[0]=1;
for(int i=1;i<N;i++)p1[i]=p1[i-1]*bas1%mod1,p2[i]=p2[i-1]*bas2%mod2;
n=read();
scanf("%s",s+1);
for(int i=1;i<=n;i++)
s1[i]=(s1[i-1]*bas1+s[i])%mod1,s2[i]=(s2[i-1]*bas2+s[i])%mod2;
int res=0;
for(int i=n/2,p=i;i;i--){
p++,p=min(p,n/2);
while(check(i,p,n-p+1,n-i+1)==false)p--;
if(check(1,i-1,n-i+2,n))res=max(res,p);
}cout<<res;
}