1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
| const int maxl = 250000 + 5; const int maxn = maxl * 2;
llong cnt[maxn]; int len;
class SAM { public: int maxlen[maxn], link[maxn], trans[maxn][26]; int last, sz;
SAM() { Set(maxlen, 0); Set(link, 0); Set(trans, 0);
last = sz = 1; }
void extend(int ch) { int cur = ++sz, p = last; maxlen[cur] = maxlen[p] + 1; cnt[cur] = 1;
for( ; p && trans[p][ch] == 0; p = link[p]) trans[p][ch] = cur;
if(p == 0) link[cur] = 1; else { int q = trans[p][ch]; if(maxlen[q] == maxlen[p] + 1) link[cur] = q; else { int clone = ++sz; maxlen[clone] = maxlen[p] + 1;
Cpy(trans[clone], trans[q]); link[clone] = link[q];
for(; p && trans[p][ch] == q; p = link[p]) trans[p][ch] = clone; link[q] = link[cur] = clone; } }
last = cur; } };
SAM sam;
// use Radix sort instead of bfs-topoSort
int C[maxn]; int id[maxn]; llong ans[maxn];
void init() { Set(cnt, 0); Set(C, 0); Set(id, 0); Set(ans, 0); }
void rsort() { Set(C, 0); _rep(i, 1, sam.sz) C[sam.maxlen[i]]++; _rep(i, 1, len) C[i] += C[i - 1]; _forDown(i, sam.sz, 1) id[C[sam.maxlen[i]]--] = i;
_forDown(i, sam.sz, 1) { int u = id[i]; cnt[sam.link[u]] += cnt[u]; } }
void solve() { _rep(i, 1, sam.sz) ans[sam.maxlen[i]] = max(ans[sam.maxlen[i]], cnt[i]); _forDown(i, len, 1) ans[i] = max(ans[i], ans[i + 1]); }
int main() { freopen("input.txt", "r", stdin); init();
char str[maxl]; scanf("%s", str); len = strlen(str);
_for(i, 0, len) sam.extend(str[i] - 'a');
rsort(); solve(); _rep(i, 1, len) printf("%d\n", ans[i]);
}
|