试了试把SAM打个包【似乎可以优美一点…………吗?】
题目大意……大概就是给一个长度为n的字符串,输出n行,每行一个数,第i行输出长度为i的子串中,出现次数最多的是多少次……
反正right集合大小就是出现次数嘛……于是胡搞乱搞
#include<bits/stdc++.h>
#define MAXN 500057
//#define FIAZE_NAlVE
using namespace std;
struct t1{
int son[MAXN][26],dis[MAXN],pre[MAXN];
int lst,cnt;
int siz[MAXN];
void insert(int x){
int np=++cnt, p=lst;
dis[np]=dis[p]+1;
lst=np;
siz[np]=1;
for(;p&&!son[p][x];p=pre[p]) son[p][x]=np;
if(!p) return pre[np]=1,void();
int q=son[p][x];
if(dis[q]==dis[p]+1) return pre[np]=q,void();
int nq=++cnt;
dis[nq]=dis[p]+1;
pre[nq]=pre[q];
pre[q]=pre[np]=nq;
memcpy(son[nq],son[q],sizeof son[q]);
for(;p&&son[p][x]==q;p=pre[p]) son[p][x]=nq;
}
char read_s[MAXN];
int lth_s;
void build(){
lst=1,cnt=1;
scanf("%s",read_s);
lth_s=strlen(read_s);
for(int i=0;i<lth_s;++i) insert(read_s[i]-97);
}
#ifdef FIAZE_NAlVE
char tmp[MAXN];
void _check_if_correct_(int now,int stp){
for(int i=0;i<26;++i)
if(son[now][i]){
tmp[stp]=i+97;
puts(tmp);
_check_if_correct_(son[now][i],stp+1);
tmp[stp]=' ';
}
}
#endif
int v[MAXN],q[MAXN];
int ans[MAXN];
void init(){
for(int i=1;i<=cnt;++i) ++v[dis[i]];
for(int i=1;i<=lth_s;++i) v[i]+=v[i-1];
for(int i=1;i<=cnt;++i) q[v[dis[i]]--]=i;
// for(int i=1;i<=cnt;++i) printf("%d ",q[i]);
// cout<<endl;
for(int i=cnt;i;--i) siz[pre[q[i]]]+=siz[q[i]];
}
void calc(){
for(int i=1;i<=cnt;++i)
ans[dis[i]]=max(ans[dis[i]],siz[i]);
for(int i=lth_s-1;i;--i)
ans[i]=max(ans[i],ans[i+1]);
for(int i=1;i<=lth_s;++i) printf("%d\n",ans[i]);
}
}SAM_s;
int main(){
freopen("1.in","r",stdin);
freopen("orz.out","w",stdout);
SAM_s.build();
SAM_s.init();
SAM_s.calc();
return 0;
}