建立后缀自动机,对于同一个节点,出现次数是相同的(right的大小),同时满足单调性(长度越长出现次数越少),所以只需要考虑最长的串即可。
PS:似乎也并不需要求依次后缀的max,不知道为什么……
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 250005 4 int V,last,k,a[N],id[N<<1],sz[N<<1],ans[N],len[N<<1],sum[N<<1],fa[N<<1],ch[N<<1][31]; 5 char s[N]; 6 void add(int c){ 7 int p=last,np=last=++V; 8 sz[V]=1; 9 len[np]=len[p]+1; 10 for(;(p)&&(!ch[p][c]);p=fa[p])ch[p][c]=V; 11 if (!p)fa[np]=1; 12 else{ 13 int q=ch[p][c]; 14 if (len[q]==len[p]+1)fa[np]=q; 15 else{ 16 int nq=++V; 17 len[nq]=len[p]+1; 18 memcpy(ch[nq],ch[q],sizeof(ch[q])); 19 fa[nq]=fa[q]; 20 fa[q]=fa[np]=nq; 21 for(;(p)&&(ch[p][c]==q);p=fa[p])ch[p][c]=nq; 22 } 23 } 24 } 25 int main(){ 26 scanf("%s",s); 27 V=last=1; 28 for(int i=0;s[i];i++)add(s[i]-'a'); 29 for(int i=1;i<=V;i++)a[len[i]]++; 30 for(int i=0;s[i];i++)a[i+1]+=a[i]; 31 for(int i=1;i<=V;i++)id[a[len[i]]--]=i; 32 for(int i=V;i;i--){ 33 ans[len[id[i]]]=max(ans[len[id[i]]],sz[id[i]]); 34 sz[fa[id[i]]]+=sz[id[i]]; 35 } 36 for(int i=1;s[i-1];i++)printf("%d\n",ans[i]); 37 }