SPOJ - NSUBSTR
#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PII pair<int, int>
#define PLI pair<LL, int>
#define PDD pair<double,double>
#define ull unsigned long long
using namespace std;
const int N = 250000 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-8;
int n, ans[N];
char s[N];
struct SuffixAutomaton {
int last, cur, cnt, ch[N<<1][26], id[N<<1], fa[N<<1], dis[N<<1], sz[N<<1], c[N];
SuffixAutomaton() {cur = cnt = 1;}
void init() {
for(int i = 1; i <= cnt; i++) {
memset(ch[i], 0, sizeof(ch[i]));
sz[i] = c[i] = dis[i] = fa[i] = 0;
}
cur = cnt = 1;
}
void extend(int c, int id) {
last = cur; cur = ++cnt;
int p = last; dis[cur] = id;
for(; p && !ch[p][c]; p = fa[p]) ch[p][c] = cur;
if(!p) fa[cur] = 1;
else {
int q = ch[p][c];
if(dis[q] == dis[p]+1) fa[cur] = q;
else {
int nt = ++cnt; dis[nt] = dis[p]+1;
memcpy(ch[nt], ch[q], sizeof(ch[q]));
fa[nt] = fa[q]; fa[q] = fa[cur] = nt;
for(; ch[p][c]==q; p=fa[p]) ch[p][c] = nt;
}
}
sz[cur] = 1;
}
void getSize(int n) {
for(int i = 1; i <= cnt; i++) c[dis[i]]++;
for(int i = 1; i <= n; i++) c[i] += c[i-1];
for(int i = cnt; i >= 1; i--) id[c[dis[i]]--] = i;
for(int i = cnt; i >= 1; i--) {
int p = id[i];
sz[fa[p]] += sz[p];
}
}
void solve() {
for(int i = 2; i <= cnt; i++) {
ans[dis[i]] = max(ans[dis[i]], sz[i]);
}
for(int i = n-1; i >= 1; i--) ans[i] = max(ans[i], ans[i+1]);
for(int i = 1; i <= n; i++) printf("%d
", ans[i]);
}
} sam;
int main() {
scanf("%s", s + 1);
n = strlen(s + 1);
for(int i = 1; i <= n; i++)
sam.extend(s[i]-'a', i), ans[i] = 0;
sam.getSize(n);
sam.solve();
return 0;
}
/*
*/