hihocoder 1449 后缀自动机三·重复旋律6

描述

小Hi平时的一大兴趣爱好就是演奏钢琴。我们知道一个音乐旋律被表示为一段数构成的数列。

现在小Hi想知道一部作品中所有长度为K的旋律中出现次数最多的旋律的出现次数。但是K不是固定的,小Hi想知道对于所有的K的答案。

parants树上拓扑

合并endpos

 1 #pragma GCC optimize(2)
 2 #pragma G++ optimize(2)
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<iostream>
 7 #include<cstdio>
 8 #include<queue>
 9 
10 #define N 2000007
11 using namespace std;
12 inline int read()
13 {
14     int x=0,f=1;char ch=getchar();
15     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
16     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
17     return x*f;
18 }
19 
20 int n;
21 char s[N];
22 struct sam
23 {
24     int last,cnt,rt;
25     int c[N][26],fa[N],mx[N],endpos[N];
26     sam(){last=cnt=rt=1;}
27     void extend(int x)
28     {
29         int p=last,np=last=++cnt;mx[np]=mx[p]+1,endpos[np]=1;
30         while(p&&!c[p][x])
31         {
32             c[p][x]=np;
33             p=fa[p];
34         }
35         if(!p)fa[np]=rt;
36         else
37         {
38             int q=c[p][x];
39             if(mx[q]==mx[p]+1)fa[np]=q;
40             else
41             {
42                 int nq=++cnt;mx[nq]=mx[p]+1;
43                 memcpy(c[nq],c[q],sizeof(c[q]));
44                 fa[nq]=fa[q];
45                 fa[q]=fa[np]=nq;
46                 while(c[p][x]==q)c[p][x]=nq,p=fa[p];
47             }
48         }
49     }
50     int du[N],now=1,pre=0;queue<int>q[2];
51     void init_endpos()
52     {
53         memset(du,0,sizeof(du));
54         for (int i=cnt;i>1;i--)
55             du[fa[i]]++;
56         for (int i=1;i<=cnt;i++)
57             if(!du[i])q[pre].push(i),du[i]=-1;
58         while(!q[pre].empty())
59         {
60             while(!q[pre].empty())
61             {
62                 int x=q[pre].front();q[pre].pop();
63                 endpos[fa[x]]+=endpos[x];
64                 du[fa[x]]--;
65                 if(!du[fa[x]])q[now].push(fa[x]);
66             }
67             swap(pre,now);
68         }
69     }
70     int ans[N];
71     void solve()
72     {
73         memset(ans,0,sizeof(ans));
74         for (int i=1;i<=cnt;i++)
75             ans[mx[i]]=max(ans[mx[i]],endpos[i]);
76         for (int i=n-1;i>=1;i--)
77             ans[i]=max(ans[i],ans[i+1]);
78         for (int i=1;i<=n;i++)
79             printf("%d
",ans[i]);
80     }
81 }sam;
82 
83 int main()
84 {
85     scanf("%s",s+1),n=strlen(s+1);
86     for (int i=1;i<=n;i++)
87         sam.extend(s[i]-'a');
88     sam.init_endpos();
89     sam.solve();
90 }
原文地址:https://www.cnblogs.com/fengzhiyuan/p/8503928.html