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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
| #include <cstring> #include <iostream> using namespace std; const int N = 1e5 + 5, INF = 0x3f3f3f3f; int n; int siz[N * 2], c[N * 2], pos[N * 2], a[N * 2]; char s[N]; namespace SAM { int nxt[N * 2][27], link[N * 2], len[N * 2]; int cnt = 1, last = 1; void insert(int c) { int cur = ++cnt; int p = last; last = cur; len[cur] = len[p] + 1; siz[cur] = 1; pos[cur] = len[cur]; while (p && !nxt[p][c]) { nxt[p][c] = cur; p = link[p]; } if (!p) { link[cur] = 1; } else { int q = nxt[p][c]; if (len[p] + 1 == len[q]) { link[cur] = q; } else { int cq = ++cnt; len[cq] = len[p] + 1; memcpy(nxt[cq], nxt[q], sizeof(nxt[q])); link[cq] = link[q]; link[q] = link[cur] = cq; while (p && nxt[p][c] == q) { nxt[p][c] = cq; p = link[p]; } } } } } using namespace SAM; struct Segment_Tree { #define ls(x) x * 2 #define rs(x) x * 2 + 1 int tree[N << 2], tag[N << 2]; Segment_Tree() { memset(tag, 0x3f3f, sizeof(tag)); memset(tree, 0x3f3f, sizeof(tree)); } void pushdown(int x) { tag[ls(x)] = min(tag[ls(x)], tag[x]); tag[rs(x)] = min(tag[rs(x)], tag[x]); tree[ls(x)] = min(tree[ls(x)], tag[x]); tree[rs(x)] = min(tree[rs(x)], tag[x]); tag[x] = INF; } void update(int x, int l, int r, int L, int R, int d) { if (l > R || r < L) return; if (l >= L && r <= R) { tree[x] = min(tree[x], d); tag[x] = min(tag[x], d); return; } pushdown(x); int mid = (l + r) >> 1; update(ls(x), l, mid, L, R, d); update(rs(x), mid + 1, r, L, R, d); tree[x] = min(tree[ls(x)], tree[rs(x)]); } int query(int x, int l, int r, int pos) { if (l == r) { return tree[x]; } pushdown(x); int mid = (l + r) >> 1; if (pos <= mid) { return query(ls(x), l, mid, pos); } else { return query(rs(x), mid + 1, r, pos); } } #undef ls #undef rs } A, B; int main() { cin >> s + 1; n = strlen(s + 1); for (int i = 1; i <= n; ++i) SAM::insert(s[i] - 'a'); for (int i = 1; i <= cnt; ++i) ++c[len[i]]; for (int i = 1; i <= cnt; ++i) c[i] += c[i - 1]; for (int i = 1; i <= cnt; ++i) a[c[len[i]]--] = i; for (int i = cnt; i; --i) { siz[link[a[i]]] += siz[a[i]]; pos[link[a[i]]] = max(pos[link[a[i]]], pos[a[i]]); } for (int i = 1; i <= cnt; ++i) { if (siz[i] == 1) { int l = len[link[i]], r = len[i]; A.update(1, 1, n, pos[i] - l, pos[i], l + 1); B.update(1, 1, n, pos[i] - r + 1, pos[i] - l, pos[i] + 1); } } for (int i = 1; i <= n; ++i) { cout << min(A.query(1, 1, n, i), B.query(1, 1, n, i) - i) << endl; } return 0; }
|