【题目链接】
【双倍经验链接】
【思路要点】
- 补档博客,无题解。
【代码】
#include<bits/stdc++.h> using namespace std; #define MAXN 200005 struct Segment_Tree { int lc[MAXN], rc[MAXN], ans[MAXN]; int root, size, n, INF; int new_node() { lc[size] = rc[size] = ans[size]; return size++; } void build(int root, int l, int r) { ans[root] = INF; if (l == r) return; int mid = (l + r) / 2; lc[root] = new_node(); build(lc[root], l, mid); rc[root] = new_node(); build(rc[root], mid + 1, r); } void init(int x) { size = 0; n = x; INF = 1e9; root = new_node(); build(root, 1, n); } void pushdown(int pos) { ans[lc[pos]] = min(ans[lc[pos]], ans[pos]); ans[rc[pos]] = min(ans[rc[pos]], ans[pos]); ans[pos] = INF; } void modify(int pos, int l, int r, int ql, int qr, int v) { if (ql == l && r == qr) { ans[pos] = min(ans[pos], v); return; } int mid = (l + r) / 2; if (ql <= mid) modify(lc[pos], l, mid, ql, min(qr, mid), v); if (qr >= mid + 1) modify(rc[pos], mid + 1, r, max(mid + 1, ql), qr, v); } void modify(int l, int r, int v) { if (l > r) return; modify(root, 1, n, l, r, v); } int query(int pos, int l, int r, int x) { if (l == r) return ans[pos]; pushdown(pos); int mid = (l + r) / 2; if (x <= mid) return query(lc[pos], l, mid, x); else return query(rc[pos], mid + 1, r, x); } int query(int x) { return query(root, 1, n, x); } } A, B; struct Suffix_Automaton { int child[MAXN][26]; int father[MAXN], depth[MAXN]; vector <int> a[MAXN]; int cnt[MAXN], end[MAXN]; int root, size, last, len; int new_node(int dep) { memset(child[size], 0, sizeof(child[size])); father[size] = 0; depth[size] = dep; a[size].clear(); cnt[size] = 0; return size++; } void init() { size = 0; root = last = new_node(0); } void Extend(int ch, int pos) { int np = new_node(depth[last] + 1); int p = last; for (; child[p][ch] == 0; p = father[p]) child[p][ch] = np; if (child[p][ch] == np) father[np] = root; else { int q = child[p][ch]; if (depth[p] + 1 == depth[q]) father[np] = q; else { int nq = new_node(depth[p] + 1); father[nq] = father[q]; father[q] = father[np] = nq; memcpy(child[nq], child[q], sizeof(child[q])); for (; child[p][ch] == q; p = father[p]) child[p][ch] = nq; } } last = np; cnt[np] = 1; end[np] = pos; } void insert(char *s) { len = strlen(s + 1); for (int i = 1; i <= len; i++) Extend(s[i] - 'a', len - i + 1); } void maintain(int pos) { if (pos == root) return; int fa = father[pos]; A.modify(end[pos], end[pos] + depth[fa], depth[fa] + 1); B.modify(end[pos] + depth[fa], len, 1 - end[pos]); } void work(int pos) { if (a[pos].size() == 1) { work(a[pos][0]); cnt[pos] += cnt[a[pos][0]]; end[pos] = end[a[pos][0]]; if (cnt[pos] == 1) maintain(pos); else end[pos] = 0; } else { for (unsigned i = 0; i < a[pos].size(); i++) { work(a[pos][i]); cnt[pos] += cnt[a[pos][i]]; end[pos] = end[a[pos][i]]; } if (cnt[pos] == 1) maintain(pos); else end[pos] = 0; } } void build() { for (int i = 1; i < size; i++) a[father[i]].push_back(i); work(root); } } SAM; char s[MAXN]; int main() { scanf("%s", s + 1); SAM.init(); for (int i = 1, j = strlen(s + 1); i < j; i++, j--) swap(s[i], s[j]); SAM.insert(s); int n = strlen(s + 1); A.init(n); B.init(n); SAM.build(); for (int i = 1; i <= n; i++) printf("%d\n", min(A.query(i), B.query(i) + i)); return 0; }