hash
直接求一遍前缀积后缀积
然后枚举长度和左端点做就可以了
下面是代码
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
#define N 200010
const int base=2333;
const int mod=987654321;
using namespace std;
int a[N],h[N],g[N],cf[N];
int ans[N];
map<int,bool>p;
int geth(int x,int y){
x--;
return ((h[y]-(long long)h[x]*cf[y-x]%mod)+mod)%mod;
}
int getg(int x,int y){
y++;
return ((g[x]-(long long)g[y]*cf[y-x]%mod)+mod)%mod;
}
int main(){
int n;
cin>>n;
int i,j,x,y;
cf[0]=1;
for(i=1;i<=n;i++){
cf[i]=(long long)cf[i-1]*base%mod;
}
for(i=1;i<=n;i++){
cin>>a[i];
h[i]=((long long)h[i-1]*base+a[i])%mod;
}
for(i=n;i>=1;i--){
g[i]=((long long)g[i+1]*base+a[i])%mod;
}
int maxn=0;
int tot=0;
for(i=1;maxn*i<=n;i++){
p.clear();
int now=0;
for(j=1;j+i-1<=n;j+=i){
int h1=geth(j,j+i-1);
int h2=getg(j,j+i-1);
if(!p[h1]||!p[h2]){
now++;
p[h1]=p[h2]=true;
}
}
if(now>maxn){
maxn=now;
tot=1;
ans[1]=i;
}else if(now==maxn){
tot++;
ans[tot]=i;
}
}
cout<<maxn<<" "<<tot<<endl<<ans[1];
for(i=2;i<=tot;i++){
cout<<" "<<ans[i];
}
return 0;
}
/*
in:
21
1 1 1 2 2 2 3 3 3 1 2 3 3 1 2 2 1 3 3 2 1
out:
6 1
2
*/