本来是个回文自动机模板题
但是也可以用后缀自动机AC掉
先跑manacher
这可以识别所有的回文串
然后放进自动机里暴力跑就是了
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
typedef int INT;
#define LL long long
const int N=1e6+2e5;
char S[N];
struct SAM{
struct Node{
int pre;
int step;
int vis[27];
}SA[N];
int cnt,last;
int idx[N];
LL siz[N];
int RL[N];
int C[N];
int A[N];
int fa[N][22];
// int G[N];
LL ans;
inline void Insert(char C,int Id){
int p=last;
int np=++cnt;
last=np;
idx[Id]=np;
SA[np].step=SA[p].step+1;
for(;!SA[p].vis[C-'a'];p=SA[p].pre)SA[p].vis[C-'a']=np;
if(!p)SA[np].pre=1;
else{
int q=SA[p].vis[C-'a'];
if(SA[q].step==SA[p].step+1){
SA[np].pre=q;
}
else{
int nq=++cnt;
SA[nq].step=SA[p].step+1;
memcpy(SA[nq].vis,SA[q].vis,sizeof(SA[q].vis));
SA[nq].pre=SA[q].pre;
SA[np].pre=SA[q].pre=nq;
for(;SA[p].vis[C-'a']==q;p=SA[p].pre)SA[p].vis[C-'a']=nq;
}
}
siz[np]=1;
}
void Add(char *S){
cnt=last=1;
int len=strlen(S+1);
for(int i=1;i<=len;i++)Insert(S[i],i);//,G[S[i]-'a']++;
for(int i=1;i<=cnt;i++)C[SA[i].step]++;
for(int i=1;i<=len;i++)C[i]+=C[i-1];
for(int i=1;i<=cnt;i++)A[C[SA[i].step]--]=i;
for(int i=cnt;i>=1;i--){
int fa=SA[A[i]].pre;
siz[fa]+=siz[A[i]];
}
for(int i=1;i<=cnt;i++){
fa[A[i]][0]=SA[A[i]].pre;
for(int j=1;j<=20;j++){
fa[A[i]][j]=fa[fa[A[i]][j-1]][j-1];
}
}
}
void Get_Siz(int s,int t){
int x=idx[t];
for(int i=20;i>=0;i--)if(SA[fa[x][i]].step>=t-s+1)x=fa[x][i];
ans=max(ans,(LL)(t-s+1)*siz[x]);
}
void Print(int s,int t){
for(int i=s;i<=t;i++)cout<<S[i];
}
int key;
void Manacher(char *S){
int MaxRight=0;
int pos=0;int len=strlen(S+1);
for(int i=1;i<=len;i++){
if(MaxRight>i)RL[i]=min(RL[2*pos-i],MaxRight-i);
else{RL[i]=1;Get_Siz(i,i);}
while(i-RL[i]>0&&S[i-RL[i]]==S[i+RL[i]]&&i+RL[i]<=len){
RL[i]++;
Get_Siz(i-RL[i]+1,i+RL[i]-1);
}
if(i+RL[i]>MaxRight){
MaxRight=i+RL[i];
pos=i;
}
}
MaxRight=0;
pos=0;
for(int i=1;i<=len;i++){
if(MaxRight>i)RL[i]=min(RL[2*pos-i],MaxRight-i);
else RL[i]=0;
while(i-RL[i]>0&&S[i-RL[i]]==S[i+RL[i]+1]&&i+RL[i]<=len){
RL[i]++;
Get_Siz(i-RL[i]+1,i+RL[i]);
}
if(i+RL[i]>MaxRight){
MaxRight=i+RL[i];
pos=i;
}
}
}
void Solve(){
scanf("%s",S+1);
Add(S);
Manacher(S);
cout<<ans;
}
}Solution;
INT main(){
// freopen("3751.in","r",stdin);
// freopen("3751.out","w",stdout);
Solution.Solve();
return 0;
}