【题目链接】
【双倍经验链接】
【思路要点】
- 补档博客,无题解。
【代码】
#include<bits/stdc++.h> using namespace std; #define MAXN 200005 #define MAXL 100005 struct Suffix_Automaton { map <char, int> child[MAXN]; int father[MAXN], depth[MAXN]; int root, size, last, timer; vector <int> colour[MAXN], a[MAXN]; int num[MAXN], right[MAXN], home[MAXN], value[MAXN]; long long ans[MAXN]; int new_node(int dep) { depth[size] = dep; father[size] = 0; child[size].clear(); colour[size].clear(); a[size].clear(); num[size] = right[size] = 0; value[size] = 0; return size++; } void init() { size = 0; root = last = new_node(0); } void Extend(char ch, int col) { int np = child[last][ch]; if (np) { if (depth[np] == depth[last] + 1) { colour[np].push_back(col); last = np; } else { int nq = new_node(depth[last] + 1); father[nq] = father[np]; father[np] = nq; child[nq] = child[np]; for (int p = last; child[p][ch] == np; p = father[p]) child[p][ch] = nq; colour[nq].push_back(col); last = nq; } } else { 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) { colour[np].push_back(col); last = np; return; } int q = child[p][ch]; if (depth[q] == depth[p] + 1) { father[np] = q; colour[np].push_back(col); last = np; return; } else { int nq = new_node(depth[p] + 1); father[nq] = father[q]; father[np] = father[q] = nq; child[nq] = child[q]; for (; child[p][ch] == q; p = father[p]) child[p][ch] = nq; colour[np].push_back(col); last = np; } } } void insert(char *s, int col) { int len = strlen(s + 1); last = root; ans[col] = 0; for (int i = 1; i <= len; i++) Extend(s[i], col); } void work(int pos) { num[pos] = ++timer; home[timer] = pos; for (unsigned i = 0; i < a[pos].size(); i++) work(a[pos][i]); right[pos] = timer; } void build() { for (int i = 1; i < size; i++) a[father[i]].push_back(i); work(0); } void dfs(int pos, long long sum) { for (unsigned i = 0; i < colour[pos].size(); i++) ans[colour[pos][i]] += sum; for (unsigned i = 0; i < a[pos].size(); i++) dfs(a[pos][i], sum + value[a[pos][i]]); } } SAM; struct Query { int home, l, r; } Q[MAXN]; bool cmp(Query x, Query y) { return x.r < y.r; } int n, q, k, ans[MAXN]; int Last[MAXN], sum[MAXN]; char s[MAXL]; int query(int x) { int ans = 0; for (int i = x; i > 0; i -= i & -i) ans += sum[i]; return ans; } void change(int x, int d) { for (int i = x; i <= SAM.timer; i += i & -i) sum[i] += d; } int main() { scanf("%d%d", &n, &k); SAM.init(); for (int i = 1; i <= n; i++) { scanf("\n%s", s + 1); SAM.insert(s, i); } SAM.build(); for (int i = 0; i < SAM.size; i++) Q[++q] = (Query) {i, SAM.num[i], SAM.right[i]}; sort(Q + 1, Q + q + 1, cmp); int last = 0; for (int i = 1; i <= q; i++) { while (last < Q[i].r) { last++; int now = SAM.home[last]; for (unsigned j = 0; j < SAM.colour[now].size(); j++) { int tmp = SAM.colour[now][j]; if (Last[tmp]) change(Last[tmp], -1); change(last, 1); Last[tmp] = last; } } if (query(Q[i].r) - query(Q[i].l - 1) >= k) SAM.value[Q[i].home] = SAM.depth[Q[i].home] - SAM.depth[SAM.father[Q[i].home]]; } SAM.dfs(SAM.root, 0); for (int i = 1; i <= n; i++) printf("%lld ", SAM.ans[i]); return 0; }