You are given a string S which consists of 250000 lowercase latin letters at most. We define F(x) as the maximal number of times that some string with length x appears in S. For example for string 'ababa' F(3) will be 2 because there is a string 'aba' that occurs twice. Your task is to output F(i) for every i so that 1<=i<=|S|.
Input
String S consists of at most 250000 lowercase latin letters.
Output
Output |S| lines. On the i-th line output F(i).
Example
Input: ababa Output: 3 2 2 1 1
题意:给一个串,设长度为N,对于每个i(1->N),对于所有长度为i的不同的子串,F[i]为这些子串中出现次数最多的值,输出F[i]。
思路:后缀自动机,需要计算每个集合的right值(子串终点集合),那么可以对这些集合进行拓扑排序,然后累加,最后倒着维护最大值输出。
# include <iostream>
# include <cstdio>
# include <cstring>
using namespace std;
const int N = 500000+30;
char s[N];
int cnt,last;
int b[N],fa[N],mx[N],r[N],ch[N][26],f[N], id[N], ans[N];
void add(int x)
{
int c = s[x]-'a';
int p = last, np = ++cnt; last = np;
mx[np] = x;
for(; p&&!ch[p][c]; p=fa[p]) ch[p][c] = np;
if(!p) fa[np] = 1;
else
{
int q = ch[p][c];
if(mx[p]+1 == mx[q]) fa[np] = q;
else
{
int nq=++cnt; mx[nq] = mx[p] + 1;
memcpy(ch[nq], ch[q], sizeof ch[q]);
fa[nq] = fa[q];
fa[np] = fa[q] = nq;
for(; p&&ch[p][c]==q; p=fa[p]) ch[p][c] = nq;
}
}
}
int main()
{
last = ++cnt;
scanf("%s",s+1);
int len = strlen(s+1);
for(int i=1; i<=len; ++i) add(i);
for(int i=1,p=1; i<=len; ++i)
p = ch[p][s[i]-'a'],++f[p];//主链加上1,表示至少出现1次
for(int i=1; i<=cnt; ++i) ++b[mx[i]];//基数排序
for(int i=1; i<=len; ++i) b[i] += b[i-1];
for(int i=1; i<=cnt; ++i) id[b[mx[i]]--]=i;//排在第i的是哪个集合
for(int i=cnt; i; --i) f[fa[id[i]]] += f[id[i]];//按拓扑序累加
for(int i=1; i<=cnt; ++i) ans[mx[i]] = max(ans[mx[i]], f[i]);
for(int i=len; i; --i) ans[i]=max(ans[i+1],ans[i]);
for(int i=1; i<=len; ++i)printf("%d\n",ans[i]);
return 0;
}