题目描述
https://www.luogu.com.cn/problem/P4070
简要题意:每次添加一个字符,求添加一个字符后有多少新增加的本质不同的子串
$n\le 10^5$
Solution
每次新增的本质不同的子串的个数为 $T[np].L - T[np].l+1$
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
| #include <iostream> #include <map> #define maxn 100010 #define Maxn 200010 #define ll long long using namespace std;
int n;
struct SAM { int L; map<int, int> nxt; } T[Maxn]; int f[Maxn], last, top, rt; void init_SAM() { rt = last = top = 1; f[rt] = T[rt].L = 0; }
ll ans; void extend(int ch) { int np = ++top, p = last; last = np; T[np].L = T[p].L + 1; while (p && T[p].nxt.find(ch) == T[p].nxt.end()) T[p].nxt[ch] = np, p = f[p]; if (!p) return f[np] = rt, ans += T[np].L, void(); int q = T[p].nxt[ch]; if (T[q].L - 1 == T[p].L) f[np] = q; else { int nq = ++top; T[nq].L = T[p].L + 1; f[nq] = f[q]; T[nq].nxt = T[q].nxt; while (p && T[p].nxt[ch] == q) T[p].nxt[ch] = nq, p = f[p]; f[np] = f[q] = nq; } ans += T[np].L - T[f[np]].L; }
int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
cin >> n; init_SAM(); for (int i = 1; i <= n; ++i) { int x; cin >> x; extend(x); cout << ans << "\n"; } return 0; }
|