后缀自动机模板
详情可见luogu题解板块
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; ll max(ll a,ll b){return a>b?a:b;} #define N 2000005 struct Sam{ int nxt[N][26],fa[N],len[N],siz[N]; int n,p,q,last,ed,c[N],a[N]; char s[N];//last:自动机的末尾点 Sam(){ed=1;} void init(){ scanf("%s",s+1); n=strlen(s+1); for(int i=1;i<=n;++i) add(s[i]-'a'); } void add(int c){ p=last; len[last=++ed]=len[p]+1; siz[ed]=1; for(;p&&!nxt[p][c];p=fa[p]) nxt[p][c]=ed; if(!p){fa[ed]=1; return ;}//case 1 q=nxt[p][c]; if(len[q]==len[p]+1){fa[ed]=q; return ;}// case 2 len[++ed]=len[p]+1; memcpy(nxt[ed],nxt[q],sizeof(nxt[q])); fa[ed]=fa[q]; fa[q]=fa[ed-1]=ed; for(;nxt[p][c]==q;p=fa[p]) nxt[p][c]=ed; // case 3 } void calc(){ ll ans=0; for(int i=1;i<=ed;++i) ++c[len[i]]; for(int i=1;i<=ed;++i) c[i]+=c[i-1]; for(int i=1;i<=ed;++i) a[c[len[i]]--]=i; for(int i=ed;i;--i){//按len的长度逆序处理(显然len[fa[x]]<len[x]) siz[fa[a[i]]]+=siz[a[i]]; if(siz[a[i]]>1) ans=max(ans,1ll*siz[a[i]]*len[a[i]]); }printf("%lld",ans); } }sam; int main(){sam.init(); sam.calc(); return 0;}