link/cut tree
[kudsource.git] / SPOJ / NSUBSTR.cc
blob2f19859b358762bc7a0cef05e2325f8ac1322086
1 #include <cstdio>
2 #include <cstring>
3 #include <algorithm>
5 #define rep(i,p,q) for (i=p; i<=q; ++i)
7 using namespace std;
9 const int maxn=250000+10;
11 char str[maxn];
13 struct SAM
15 int len;
16 SAM *fail,*next[26];
17 } sam[maxn*2],*root,*last;
19 int ans[maxn]={0},cnt=0,i,sum[maxn*2],queue[maxn*2],w[maxn*2];
21 void insert(int ch)
23 SAM *p=last,*np=&sam[++cnt];
24 np->len=last->len+1;
25 last=np;
26 for (; p && !p->next[ch]; p=p->fail) p->next[ch]=np;
27 if (!p) np->fail=root; else
28 if (p->next[ch]->len==p->len+1) np->fail=p->next[ch]; else
30 SAM *q=p->next[ch],*nq=&sam[++cnt];
31 *nq=*q;
32 nq->len=p->len+1;
33 q->fail=np->fail=nq;
34 for (; p && p->next[ch]==q; p=p->fail) p->next[ch]=nq;
38 int main()
40 scanf("%s",str+1);
41 memset(sam,0,sizeof(sam));
42 last=root=&sam[++cnt];
43 int n=strlen(str+1);
44 rep(i,1,n) insert(str[i]-'a');
45 memset(sum,sizeof(sum),0);
46 SAM *now=root;
47 rep(i,1,cnt) ++sum[sam[i].len];
48 rep(i,1,n) sum[i]+=sum[i-1];
49 rep(i,1,cnt) queue[sum[sam[i].len]--]=i;
50 rep(i,1,n) ++w[(now=now->next[str[i]-'a'])-sam];
51 for (i=cnt; i; --i)
53 ans[sam[queue[i]].len]=max(ans[sam[queue[i]].len],w[queue[i]]);
54 if (sam[queue[i]].fail) w[sam[queue[i]].fail-sam]+=w[queue[i]];
56 for (i=n; i>1; --i) ans[i-1]=max(ans[i-1],ans[i]);
57 rep(i,1,n) printf("%d\n",ans[i]);
58 return 0;