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

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

时间限制:15000ms
单点时限:3000ms
内存限制:512MB

描述

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

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

解题方法提示

输入

共一行,包含一个由小写字母构成的字符串S。字符串长度不超过 1000000。

输出

共Length(S)行,每行一个整数,表示答案。

样例输入
aab
样例输出
2
1
1

小Hi讲的实在太好了,就不说什么了。

  1 /*************************************************************************
  2     > File: main.cpp
  3     > Author: You Siki
  4     > Mail: You.Siki@outlook.com 
  5     > Time: 2016年12月23日 星期五 15时14分18秒
  6  ************************************************************************/
  7 
  8 #include<bits/stdc++.h>
  9 
 10 //using namespace std;
 11 
 12 const int maxn = 2000005;
 13 
 14 /* AUTOMATON */
 15 
 16 int last = 1;
 17 int tail = 2;
 18 int fail[maxn];
 19 int step[maxn];
 20 int flag[maxn];
 21 int next[maxn][26];
 22 
 23 inline void buildAutomaton(char *s)
 24 {
 25     while (*s)
 26     {
 27         int p = last;
 28         int t = tail++;
 29         int c = *s++ - 'a';
 30 
 31         flag[t] = true;
 32         step[t] = step[p] + 1;
 33 
 34         while (p && !next[p][c])
 35             next[p][c] = t, p = fail[p];
 36 
 37         if (p)
 38         {
 39             int q = next[p][c];
 40             if (step[q] == step[p] + 1)
 41                 fail[t] = q;
 42             else
 43             {
 44                 int k = tail++;
 45                 fail[k] = fail[q];
 46                 fail[q] = fail[t] = k;
 47                 step[k] = step[p] + 1;
 48                 for (int i = 0; i < 26; ++i)
 49                     next[k][i] = next[q][i];
 50                 while (p && next[p][c] == q)
 51                     next[p][c] = k, p = fail[p];
 52             }
 53         }
 54         else
 55             fail[t] = 1;
 56         last = t;
 57     }
 58 }
 59 
 60 int que[maxn];
 61 int cnt[maxn];
 62 int ans[maxn];
 63 
 64 inline int solveAndPrintAnswer(char *s)
 65 {
 66     int hd = 0, tl = 0, n = strlen(s);
 67 
 68     for (int i = 1; i < tail; ++i)
 69         ++cnt[fail[i]];
 70 
 71     for (int i = 1; i < tail; ++i)
 72         if (!cnt[i])que[tl++] = i;
 73 
 74     while (hd != tl)
 75     {
 76         int t = que[hd++];
 77         flag[fail[t]] += flag[t];
 78         if (--cnt[fail[t]] == 0)
 79             que[tl++] = fail[t];
 80     }
 81 
 82     for (int i = 1; i < tail; ++i)
 83         if (ans[step[i]] < flag[i])
 84             ans[step[i]] = flag[i];
 85 
 86     for (int i = n; i; --i)
 87         if (ans[i] < ans[i + 1])
 88             ans[i] = ans[i + 1];
 89 
 90     for (int i = 1; i <= n; ++i)
 91         printf("%d
", ans[i]);
 92 }
 93 
 94 /* MAIN FUNC */
 95 
 96 char str[maxn];
 97 
 98 signed main(void) 
 99 {
100     scanf("%s", str);
101     buildAutomaton(str);
102     solveAndPrintAnswer(str);
103 }

@Author: YouSiki

原文地址:https://www.cnblogs.com/yousiki/p/6215041.html