洛谷3804:【模板】后缀自动机——题解
https://www.luogu.org/problemnew/show/P3804
给定一个只包含小写字母的字符串S ,
请你求出 S 的所有出现次数不为 1 的子串的出现次数乘上该子串长度的最大值。
(重学OI)
先写一个后缀自动机。
然后对最远距离l排序,然后从大到小扫一遍,有结论fa[i]的串一定有i的串。
所以累加即可。
对着这个博客的解释可以更加深刻理解:https://blog.csdn.net/clover_hxy/article/details/53758535
#include<cstdio> #include<iostream> #include<queue> #include<cstring> #include<algorithm> #include<cctype> using namespace std; typedef long long ll; const int N=2e6+5; struct tree{ int a[26],fa,l; }tr[N<<1]; char s[N]; int last,cnt; int a[N],w[N],size[N]; ll ans=0; inline void insert(int c){ int p=last,np=++cnt; last=np;tr[np].l=tr[p].l+1; for(;p&&!tr[p].a[c];p=tr[p].fa)tr[p].a[c]=np; if(!p)tr[np].fa=1; else{ int q=tr[p].a[c]; if(tr[p].l+1==tr[q].l)tr[np].fa=q; else{ int nq=++cnt;tr[nq].l=tr[p].l+1; memcpy(tr[nq].a,tr[q].a,sizeof(tr[q].a)); tr[nq].fa=tr[q].fa;tr[q].fa=tr[np].fa=nq; for(;tr[p].a[c]==q;p=tr[p].fa)tr[p].a[c]=nq; } } size[np]=1; } int main(){ scanf("%s",s); int len=strlen(s); last=cnt=1; for(int i=0;i<len;i++)insert(s[i]-'a'); for(int i=1;i<=cnt;i++)w[tr[i].l]++; for(int i=1;i<=cnt;i++)w[i]+=w[i-1]; for(int i=1;i<=cnt;i++)a[w[tr[i].l]--]=i; for(int i=cnt;i>=1;i--){ int p=a[i]; size[tr[p].fa]+=size[p]; if(size[p]>1)ans=max(ans,(ll)size[p]*tr[p].l); } printf("%lld\n",ans); return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++