本质不同的回文串只有
O(n)
个 就是做manacher时变长的时候
那么直接在SAM上找找出现几次就好了
回文自动机?我不会啊
#include<cstdio>
#include<cstdlib>
#include<map>
#include<algorithm>
using namespace std;
typedef long long ll;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read(char *s){
char c=nc(); int len=0;
for (;!(c>='a' && c<='z');c=nc());
for (;c>='a' && c<='z';s[++len]=c,c=nc()); s[++len]=0; return len-1;
}
const int N=600005;
struct state{
int len,link,next[26];
//map<int,int> next;
}st[N];
int last,ncnt;
int cnt[N];
inline void Extend(int c){
int cur=++ncnt,p;
st[cur].len=st[last].len+1; cnt[cur]=1;
for (p=last;p && !st[p].next[c];p=st[p].link)
st[p].next[c]=cur;
if (!p)
st[cur].link=1;
else{
int q=st[p].next[c];
if (st[q].len==st[p].len+1)
st[cur].link=q;
else{
int nq=++ncnt;
st[nq].len=st[p].len+1;
st[nq].link=st[q].link;
for (int i=0;i<26;i++) st[nq].next[i]=st[q].next[i];
//st[nq].next=st[q].next;
for (;p && st[p].next[c]==q;p=st[p].link)
st[p].next[c]=nq;
st[q].link=st[cur].link=nq;
}
}
last=cur;
}
int tmp[N],c[N];
inline void Sort(){
for (int i=1;i<=ncnt;i++) c[st[i].len]++;
for (int i=1;i<=ncnt;i++) c[i]+=c[i-1];
for (int i=ncnt;i;i--) tmp[c[st[i].len]--]=i;
for (int i=ncnt;i;i--)
cnt[st[tmp[i]].link]+=cnt[tmp[i]];
}
const int K=19;
int fat[N][K];
inline void Pre(){
for (int i=1;i<=ncnt;i++) fat[i][0]=st[i].link;
for (int k=1;k<K;k++)
for (int i=1;i<=ncnt;i++)
fat[i][k]=fat[fat[i][k-1]][k-1];
}
int pos[N];
int nnn=0;
inline int query(int l,int r){
l=(l+1)/2; r=(r+1)/2;
//++nnn;
int x=pos[r];
for (int k=K-1;~k;k--)
if (st[fat[x][k]].len>=r-l+1)
x=fat[x][k];
return cnt[x];
}
char s[N];
int n,a[N<<1];
int f[N<<1];
ll ans;
int main(){
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
last=ncnt=1; st[1].link=0;
n=read(s);
for (int i=1;i<=n;i++)
a[2*i-1]=s[i]-'a',a[2*i]=26,Extend(s[i]-'a'),pos[i]=last;
n=2*n-1; a[n+1]=-1; a[0]=-2;
Sort(); Pre();
int id=1,x=1; f[1]=1;
x=query(1,1);
ans=max(ans,(ll)x*f[1]);
for (int i=2;i<=n;i++){
if (i<=id+f[id]-1) f[i]=min(f[2*id-i],id+f[id]-i);
else{
f[i]=1;
if (((i&1) && (f[i]&1)) || ((~i&1) && (~f[i]&1)))
ans=max(ans,(ll)query(i,i)*f[i]);
}
while (a[i-f[i]]==a[i+f[i]]){
f[i]++;
if (((i&1) && (f[i]&1)) || ((~i&1) && (~f[i]&1)))
ans=max(ans,(ll)query(i-f[i]+1,i+f[i]-1)*f[i]);
}
if (i+f[i]>id+f[id]) id=i;
}
printf("%lld\n",ans);
//printf("%d\n",nnn);
return 0;
}