#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+5;
int s1[maxn*2],s2[maxn*2],power[maxn*2];
int tot,len,L;
char s[maxn*2];
string t;
#define mod 1000000007
const __int128 y=(__int128(1)<<64)/mod;
inline int MOD(long long x){
int a=x-((x*y)>>64)*mod;
if(a>mod) a-=mod;
return a;
}
inline int gethash1(int l,int r){
return MOD(s1[r]-MOD((long long)(s1[l-1])*power[r-l+1])+1000000007);
}
inline int gethash2(int l,int r){
return MOD(s2[l]-MOD((long long)(s2[r+1])*power[r-l+1])+1000000007);
}
unordered_set<int>mp;
vector<pair<int,int> >MH;
int sa[300010],rk[300010],o[300010],w;
//inline bool cmp(int x,int y){
// if(rk[x]==rk[y]) return rk[x+w]<rk[y+w];
// return rk[x]<rk[y];
//}
int buc[300010],id[300010];
inline void binary(){
// memset(buc,0,sizeof buc);
// memset(id,0,sizeof id);
// memset(o,0,sizeof o);
int p=0,m=128;
for(int i=1;i<=L;++i) buc[rk[i]=t[i]]++;
for(int i=1;i<=m;++i) buc[i]+=buc[i-1];
for(int i=L;i>=1;--i) sa[buc[rk[i]]--]=i;
for(w=1;w<L;w<<=1,m=L){
int tot=0;
for(int i=L-w+1;i<=L;++i) id[++tot]=i;
for(int i=1;i<=L;++i) if(sa[i]>w) id[++tot]=sa[i]-w;
memset(buc,0,sizeof buc);
for(int i=1;i<=L;++i) buc[rk[i]]++;
for(int i=1;i<=m;++i) buc[i]+=buc[i-1];
for(int i=L;i>=1;--i) sa[buc[rk[id[i]]]--]=id[i];
memcpy(o,rk,sizeof o);
for(int p=0,j=1;j<=L;j++)
if(o[sa[j]]==o[sa[j-1]] && o[sa[j]+w]==o[sa[j-1]+w]) rk[sa[j]]=p;
else rk[sa[j]]=++p;
}
}
//int sp[600010],q[600010];
//inline void Hash(){
// q[0]=1;
// for(int i=1;i<=n;++i) q[i]=q[i-1]*131,sp[i]=sp[i-1]*131+s[i];
//}
//inline int get(int l,int r){
// return sp[r]-sp[l-1]*q[r-l+1];
//}
int h[300010];
inline void height(){
h[1]=0;
for(int i=1,k=0;i<=L;++i){
if(!rk[i]) continue;
if(k) --k;
while(i+k<=L && sa[rk[i]-1]+k<=L && t[i+k]==t[sa[rk[i]-1]+k]) ++k;
h[rk[i]]=k;
}
// for(int i=2;i<=L;++i){
// int x=sa[i-1],y=sa[i];
// int len=max(L-x+1,L-y+1);
// int p=0;
// for(int j=30;j>=0;--j){
// if(p+(1<<j)-1>len) continue;
// if(gethash3(x,x+p+(1<<j)-1)==gethash3(y,y+p+(1<<j)-1)) p+=(1<<j);
// }
// h[i]=p;
// }
// for(int i=5500;i<=5530;++i) printf("%d ",h[i]);cout<<"\n";
}
int st[300010][20];
inline void ST_work(){
for(int i=1;i<=L;++i) st[i][0]=h[i];
for(int i=1;i<=19;++i) for(int j=1;j+(1<<i)-1<=L;j++) st[j][i]=min(st[j][i-1],st[j+(1<<(i-1))][i-1]);
}
inline int ask_LCP(int l,int r){
if(l==r) return 1e9;
l++;
int k=log2(r-l+1);
return min(st[l][k],st[r-(1<<k)+1][k]);
}
long long ans=0;
inline int SAP(int l,int r){
int u=rk[l];
int p=u;
for(int i=log2(u);i>=0;--i){
if(p-(1<<i)<1) continue;
if(ask_LCP(p-(1<<i),u)>=r-l+1) p-=(1<<i);
}
int q=u;
for(int i=log2(L-u+1);i>=0;--i){
if(q+(1<<i)>L) continue;
if(ask_LCP(p,q+(1<<i))>=r-l+1) q+=(1<<i);
}
return q-p+1;
}
signed main() {
ios::sync_with_stdio(0);
// freopen("P3649_54.in","r",stdin);
cin>>t;
L=len=t.size();
t=" "+t;
s[++tot]='~';
for(int i=1;i<=len;++i)
s[++tot]=t[i],s[++tot]='~';
// for(int i=1;i<=len;++i) s3[i]=(s3[i-1]*131+t[i]-'a'+1)%1000000007;
len=tot;
power[0]=1;
for(int i=1;i<=len;++i){
power[i]=MOD(power[i-1]*131ll);
s1[i]=MOD(s1[i-1]*131ll+s[i]-'a'+1);
}
for(int i=len;i>=1;--i)
s2[i]=MOD(s2[i+1]*131ll+s[i]-'a'+1);
for(int i=2;i<=len;++i){
int p=0;
for(int j=20;j>=0;--j){
if(i-p-(1<<j)<=0 || i+p+(1<<j)>len) continue;
if(gethash1(i-p-(1<<j),i+p+(1<<j))==gethash2(i-p-(1<<j),i+p+(1<<j))) p+=(1<<j);
}
if(p==0 && (i&1)) continue;
int q=0;
for(int j=20;j>=0;--j){
if(q+(1<<j)>p) continue;
if(mp.count(gethash1(i-q-(1<<j),i+q+(1<<j)))) q+=(1<<j);
}
q++;
for(int j=p;j>=q;j-=2) MH.push_back({(i-j+1)/2,(i+j)/2}),mp.insert(gethash1(i-j,i+j)),mp.insert(gethash1(i-j-1,i+j+1));
}
mp.clear();
binary();
height();
ST_work();
for(int i=0;i<MH.size();++i){
int l=MH[i].first,r=MH[i].second;
ans=max(ans,(long long)(r-l+1)*SAP(l,r));
}
cout<<ans;
return 0;
}
就差几十毫秒了。
思路是用 Hash 找出所有本质不同的回文串,然后用 SA 暴力去匹配。
MLE 的方法找到了,现在主要是 TLE 了。