【题目链接】
【思路要点】
- 补档博客,无题解。
【代码】
#include<bits/stdc++.h> using namespace std; #define MAXN 1000005 #define MAXM 3000005 #define MAXLOG 22 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; } int n, m, a[MAXM]; char s[MAXN]; struct Suffix_Automaton { int depth[MAXN], home[MAXN]; int father[MAXN][MAXLOG]; int child[MAXN][26]; vector <int> a[MAXN], b[MAXN]; int size, root, last, timer; int dfn[MAXN], dep[MAXN]; int index[MAXN], Len; long long cnt[MAXN]; long long ans, now; int new_node(int dep) { depth[size] = dep; return size++; } void Extend(int ch) { int p = last, np = new_node(depth[p] + 1); while (child[p][ch] == 0) { child[p][ch] = np; p = father[p][0]; } if (child[p][ch] == np) father[np][0] = root; else { int q = child[p][ch]; if (depth[p] + 1 == depth[q]) father[np][0] = q; else { int nq = new_node(depth[p] + 1); father[nq][0] = father[q][0]; father[np][0] = father[q][0] = nq; memcpy(child[nq], child[q], sizeof(child[q])); while (child[p][ch] == q) { child[p][ch] = nq; p = father[p][0]; } } } last = np; } void dfs(int pos) { dfn[pos] = ++timer; for (unsigned i = 0; i < a[pos].size(); i++) { dep[a[pos][i]] = dep[pos] + 1; dfs(a[pos][i]); } } void init(int len, char *s) { Len = len; size = timer = 0; root = last = new_node(0); for (int i = 1; i <= len; i++) { Extend(s[i] - 'a'); home[i] = last; } for (int i = 1; i < size; i++) a[father[i][0]].push_back(i); for (int p = 1; p < MAXLOG; p++) for (int i = 1; i < size; i++) father[i][p] = father[father[i][p - 1]][p - 1]; dfs(0); } int Lca(int x, int y) { if (dep[x] < dep[y]) swap(x, y); for (int p = MAXLOG - 1; p >= 0; p--) if (dep[father[x][p]] >= dep[y]) x = father[x][p]; if (x == y) return x; for (int p = MAXLOG - 1; p >= 0; p--) if (father[x][p] != father[y][p]) { x = father[x][p]; y = father[y][p]; } return father[x][0]; } void getcnt(int pos) { cnt[pos] = index[pos]; for (unsigned i = 0; i < b[pos].size(); i++) { getcnt(b[pos][i]); cnt[pos] += cnt[b[pos][i]]; } } void work(int root) { now += cnt[root] * depth[root]; if (index[root]) ans += now; for (unsigned i = 0; i < b[root].size(); i++) { now -= cnt[b[root][i]] * depth[root]; work(b[root][i]); now += cnt[b[root][i]] * depth[root]; } now -= cnt[root] * depth[root]; } long long query(int n, int *pos) { static int Stack[MAXN], Queue[MAXN]; int top = 0, tot = 0; Stack[++top] = Queue[++tot] = root; for (int i = 1; i <= n; i++) { int now = pos[i]; index[now] = 1; int lca = Lca(now, Stack[top]); if (lca == Stack[top]) Stack[++top] = Queue[++tot] = now; else { while (dfn[lca] < dfn[Stack[top - 1]]) { b[Stack[top - 1]].push_back(Stack[top]); top--; } if (lca == Stack[top - 1]) { b[lca].push_back(Stack[top--]); Stack[++top] = Queue[++tot] = now; } else { b[lca].push_back(Stack[top--]); Stack[++top] = Queue[++tot] = lca; Stack[++top] = Queue[++tot] = now; } } } for (int i = 1; i < top; i++) b[Stack[i]].push_back(Stack[i + 1]); ans = now = 0; getcnt(root); work(root); for (int i = 1; i <= tot; i++) { int tmp = Queue[i]; ans -= index[tmp] * depth[tmp]; index[tmp] = cnt[tmp] = 0; b[tmp].clear(); } return ans / 2; } } SAM; bool cmp(int x, int y) { return SAM.dfn[x] < SAM.dfn[y]; } int main() { read(n), read(m); scanf("\n%s", s + 1); reverse(s + 1, s + n + 1); SAM.init(n, s); for (int i = 1; i <= m; i++) { int x; read(x); for (int j = 1; j <= x; j++) read(a[j]), a[j] = SAM.home[n - a[j] + 1]; sort(a + 1, a + x + 1, cmp); x = unique(a + 1, a + x + 1) - (a + 1); printf("%lld\n", SAM.query(x, a)); } return 0; }