luogu 3804 【模板】后缀自动机
学习一波后缀自动机
求字符串$S$的所有出现次数不为1的子串的出现次数乘上该子串长度的最大值
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 #include<cstring> 7 #include<vector> 8 #include<queue> 9 #include<map> 10 #define rep(i,s,t) for(register int i=(s);i<=(t);++i) 11 #define dwn(i,s,t) for(register int i=(s);i>=(t);--i) 12 #define ren for(register int i=fst[x];i;i=nxt[i]) 13 #define Fill(x,t) memset(x,t,sizeof(x)) 14 #define ll long long 15 #define inf 2139062143 16 #define MAXN 2001000 17 using namespace std; 18 char s[MAXN]; 19 int n,rt,lst,tr[MAXN][26],tot,sz[MAXN],mxlen[MAXN],rnk[MAXN],cnt[MAXN],fa[MAXN]; 20 ll ans; 21 inline void extend(int c) 22 { 23 int p=lst,np=lst=++tot;mxlen[np]=mxlen[p]+1,sz[np]=1; 24 for(;p&&!tr[p][c];p=fa[p]) tr[p][c]=np; 25 if(!p) {fa[np]=rt;return ;} 26 int q=tr[p][c];if(mxlen[q]==mxlen[p]+1) {fa[np]=q;return ;} 27 int nq=++tot;mxlen[nq]=mxlen[p]+1; 28 memcpy(tr[nq],tr[q],sizeof(tr[nq])); 29 fa[nq]=fa[q],fa[np]=fa[q]=nq; 30 for(;p&&tr[p][c]==q;p=fa[p]) tr[p][c]=nq; 31 } 32 void build() 33 { 34 rep(i,1,tot) cnt[mxlen[i]]++;rep(i,1,n) cnt[i]+=cnt[i-1]; 35 rep(i,1,tot) rnk[cnt[mxlen[i]]--]=i;int p; 36 dwn(i,tot,1) 37 { 38 p=rnk[i],sz[fa[p]]+=sz[p]; 39 if(sz[p]>1) ans=max(ans,1LL*sz[p]*mxlen[p]); 40 } 41 } 42 int main() 43 { 44 rt=lst=tot=1;scanf("%s",s+1);n=strlen(s+1); 45 rep(i,1,n) extend(s[i]-'a'); 46 build();printf("%lld\n",ans); 47 }