http://www.lydsy.com/JudgeOnline/problem.php?id=3879
SvT的中文是后缀虚树?
反正本蒟蒻不懂,还是$O(nlogn)$的后缀数组和单调栈维护来做,fye学姐讲了这种学法(当时并没有听懂QwQ),xiaoyimi教会了我这种做法→xiaoyimi的题解。
一开始贡献了2次TLE,以为是玄学的死循环,果断挂起对拍器拍了一晚上,然后在回家的路上才想起来TLE是因为提交的时候忘删freopen了
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int N = 500003; const ll p = 23333333333333333ll; int in() { int k = 0, fh = 1; char c = getchar(); for(; c < ‘0‘ || c > ‘9‘; c = getchar()) if (c == ‘-‘) fh = -1; for(; c >= ‘0‘ && c <= ‘9‘; c = getchar()) k = (k << 3) + (k << 1) + c - ‘0‘; return k * fh; } int c[N], t1[N], t2[N]; void st(int *x, int *y, int *sa, int n, int m) { for(int i = 0; i < m; ++i) c[i] = 0; for(int i = 0; i < n; ++i) ++c[x[y[i]]]; for(int i = 1; i < m; ++i) c[i] += c[i - 1]; for(int i = n - 1; i >= 0; --i) sa[--c[x[y[i]]]] = y[i]; } void mkhz(int *r, int *sa, int n, int m) { int *x = t1, *y = t2, *t, p, i, j; for(i = 0; i < n; ++i) x[i] = r[i], y[i] = i; st(x, y, sa, n, m); for(p = 1, j = 1; p < n; m = p, j <<= 1) { for(p = 0, i = n - j; i < n; ++i) y[p++] = i; for(i = 0; i < n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j; st(x, y, sa, n, m); for(t = x, x = y, y = t, p = 1, x[sa[0]] = 0, i = 1; i < n; ++i) x[sa[i]] = y[sa[i]] == y[sa[i - 1]] && y[sa[i] + j] == y[sa[i - 1] + j] ? p - 1 : p++; } } void mkh(int *r, int *sa, int *rank, int *h, int n) { int k = 0, j, i; for(i = 0; i < n; ++i) rank[sa[i]] = i; for(i = 1; i < n; h[rank[i++]] = k) for(k ? --k : 0, j = sa[rank[i] - 1]; r[i + k] == r[j + k]; ++k); } char s[N]; int n, m, sa[N], rank[N], r[N], h[N], f[N][20], Log_2[N], a[N]; int get_min(int l, int r) { int len = Log_2[r - l]; return min(f[l][len], f[r - (1 << len)][len]); } int get_LCP(int l, int r) { l = rank[l]; r = rank[r]; if (l > r) swap(l, r); return get_min(l, r); } bool cmp(int x, int y) { return rank[x] < rank[y]; } int sta[N], top, bef[N], size[N]; void sub(ll &x, ll y) { x -= y; if (x < 0) x += p; } void add(ll &x, ll y) { x += y; if (x > p) x -= p; } int main() { n = in(); m = in(); scanf("%s", s + 1); r[0] = 0; for(int i = 1; i <= n; ++i) r[i] = s[i] - ‘a‘ + 1; mkhz(r, sa, n + 1, 27); mkh(r, sa, rank, h, n + 1); for(int i = 0; i < n; ++i) f[i][0] = h[i + 1]; for(int j = 1; j < 20; ++j) for(int i = 0; i < n; ++i) { if (i + (1 << (j - 1)) >= n) break; f[i][j] = min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]); } int tmp = 0; for(int i = 1; i <= n; ++i) { if ((1 << (tmp + 1)) < i) ++tmp; Log_2[i] = tmp; } int tot; ll sum, ans = 0; while (m--) { tot = in(); for(int i = 1; i <= tot; ++i) a[i] = in(); sort(a + 1, a + tot + 1, cmp); tot = unique(a + 1, a + tot + 1) - a; --tot; for(int i = 1; i < tot; ++i) bef[i] = get_LCP(a[i], a[i + 1]); top = 0; sum = 0; ans = 0; for(int i = 1; i < tot; ++i) { size[i] = 1; while (top && bef[i] < bef[sta[top]]) { sub(sum, 1ll * bef[sta[top]] * size[sta[top]] % p); size[i] += size[sta[top]]; --top; } sta[++top] = i; add(sum, 1ll * bef[i] * size[i] % p); add(ans, sum); } printf("%lld\n", ans); } return 0; }
再一次被自己的智商感动QAQ
时间: 2024-10-19 19:24:36