【思路要点】
- 枚举 i−ji-ji−j ,计算最大的 kkk 使得 S[i−j+1…i−j+k]S[i-j+1\dots i-j+k]S[i−j+1…i−j+k] 为 S[1…i−j]S[1\dots i-j]S[1…i−j] 的子串,则由该问题的答案显然可以解决原问题。
- 需要维护字符串 S,TS,TS,T ,支持在 SSS 后加入字符,保证 TTT 是 SSS 的子串的情况下在 TTT 后加入字符,在 TTT 之前删除字符,则可使用后缀自动机完成。
- 时间复杂度 O(N)O(N)O(N) 。
【代码】
#include<bits/stdc++.h> using namespace std; const int MAXN = 1e6 + 5; typedef long long ll; typedef long double ld; typedef unsigned long long ull; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } namespace SuffixAutomaton { const int MAXN = 2e6 + 5; const int MAXC = 2; int root, size, last; int child[MAXN][MAXC]; int fail[MAXN], depth[MAXN], cnt[MAXN]; int newnode(int dep) { fail[size] = 0; depth[size] = dep; memset(child[size], 0, sizeof(child[size])); return size++; } void extend(int ch) { int p = last, np = newnode(depth[last] + 1); while (child[p][ch] == 0) { child[p][ch] = np; p = fail[p]; } if (child[p][ch] == np) fail[np] = root; else { int q = child[p][ch]; if (depth[q] == depth[p] + 1) fail[np] = q; else { int nq = newnode(depth[p] + 1); fail[nq] = fail[q]; fail[q] = fail[np] = nq; memcpy(child[nq], child[q], sizeof(child[q])); while (child[p][ch] == q) { child[p][ch] = nq; p = fail[p]; } } } cnt[last = np]++; } void init() { size = 0; root = last = newnode(0); } } int n, ans[MAXN]; char s[MAXN]; int main() { scanf("%s", s + 1); n = strlen(s + 1); SuffixAutomaton :: init(); int pos = SuffixAutomaton :: root, res = 0; for (int i = 1; i <= n; i++) { SuffixAutomaton :: extend(s[i] - '0'); while (res < i) { pos = SuffixAutomaton :: root; ans[++res] = i; } while (pos != 0 && SuffixAutomaton :: depth[SuffixAutomaton :: fail[pos]] >= res - i) pos = SuffixAutomaton :: fail[pos]; while (res < n && SuffixAutomaton :: child[pos][s[res + 1] - '0'] != 0) { pos = SuffixAutomaton :: child[pos][s[res + 1] - '0']; ans[++res] = i; } } for (int i = 1; i <= n; i++) writeln(i - ans[i]); return 0; }