bzoj 4545 DQS 的 Trie
作者:互联网
老年选手不会 SAM 也不会 LCT 系列
我的数据结构好菜啊 qnq
一颗 Trie 树,$q$ 次询问,每次可以是:
1.求这棵树上本质不同的子串数量
2.插入一个子树,保证总大小不超过 $100000$
3.询问一个字符串在 Trie 树上出现过多少次,保证所有询问串总长度不超过 $100000$
sol:
第一问显然就是个广义 SAM,可以在每次 extend 的时候顺便算出来
第二问和第三问要求动态维护 parent 树的子树 size,差分一下就变成了链加和单点查询,LCT 维护一下即可
注意的几个细节:
如果你要匹配一个整串,串在 SAM 上跑的时候是直接走 Trans 边,不跳 parent
(注意区别于,如果你要匹配一个串的子串,在 SAM 上跑的时候要跳 parent ,注意这两个不一样
LCT 的 link 和 cut,如果你使用的是不 makeroot 的偷懒写法,是不满足交换律的,一定都是一个方向(从上往下 link / cut)
为什么我不 makeroot 啊(平时啥都敢写系列
#include <bits/stdc++.h> #define LL long long #define rep(i, s, t) for (register int i = (s), i##end = (t); i <= i##end; ++i) #define dwn(i, s, t) for (register int i = (s), i##end = (t); i >= i##end; --i) using namespace std; inline int read() { int x = 0,f = 1; char ch = getchar(); for(; !isdigit(ch); ch = getchar())if(ch == '-') f = -f; for(; isdigit(ch); ch = getchar())x = 10 * x + ch - '0'; return x * f; } const int maxn = 400010; #define ls ch[x][0] #define rs ch[x][1] char s[maxn]; int n, node[maxn]; int ch[maxn][2], fa[maxn], tag[maxn], val[maxn], st[maxn], top; inline int isroot(int x) { return (ch[fa[x]][0] != x) && (ch[fa[x]][1] != x); } inline void rotate(int x) { int y = fa[x], z = fa[y]; int l = (ch[y][1] == x), r = l ^ 1; if(!isroot(y)) ch[z][ch[z][1] == y] = x; fa[x] = z; fa[ch[x][r]] = y; fa[y] = x; ch[y][l] = ch[x][r]; ch[x][r] = y; } inline void pushdown(int x) { if(x && tag[x]) { if(ls) tag[ls] += tag[x], val[ls] += tag[x]; if(rs) tag[rs] += tag[x], val[rs] += tag[x]; tag[x] = 0; } } inline void splay(int x) { st[top = 1] = x; for(int i = x; !isroot(i); i = fa[i]) st[++top] = fa[i]; for(int i = top; i; i--) pushdown(st[i]); while(!isroot(x)) { int y = fa[x], z = fa[y]; if(!isroot(y)) { if(ch[y][0] == x ^ ch[z][0] == y) rotate(x); else rotate(y); } rotate(x); } } inline void access(int x) { for(int y = 0; x; y = x, x = fa[x]) { splay(x); rs = y; } } inline void link(int x, int y) { fa[y] = x; //cerr << "link :" << x << " " << y << endl; access(x); splay(x); val[x] += val[y]; tag[x] += val[y]; } inline void cut(int x, int y) { access(y); splay(y); //cerr << "cut :" << x << " " << y << endl; val[x] -= val[y]; tag[x] -= val[y]; fa[x] = 0; ch[y][0] = 0; } int tr[maxn][7], mxlen[maxn], pre[maxn], root, dfn; LL ans; int extend(int last, int c) { int p = last, np = last = ++dfn; mxlen[np] = mxlen[p] + 1; for(; p && !tr[p][c]; p = pre[p]) tr[p][c] = np; if(!p) pre[np] = root, link(root, np); else { int q = tr[p][c]; if(mxlen[p] + 1 == mxlen[q]) pre[np] = q, link(q, np); else { int nq = ++dfn; mxlen[nq] = mxlen[p] + 1; pre[nq] = pre[q]; link(pre[q], nq); memcpy(tr[nq], tr[q], sizeof(tr[nq])); for(; p && tr[p][c] == q; p = pre[p]) tr[p][c] = nq; cut(pre[q], q); pre[np] = pre[q] = nq; link(pre[q], q);link(pre[np], np); } } ans += ((LL)mxlen[np] - (LL)mxlen[pre[np]]); access(np); splay(np); val[np]++; tag[np]++; // cerr << np << endl; return np; } int first[maxn], to[maxn << 1], nx[maxn << 1], va[maxn], cnt; int vis[maxn], clo, par[maxn]; inline void add(int u, int v, int w) { to[++cnt] = v; va[cnt] = w; nx[cnt] = first[u]; first[u] = cnt; } void dfs(int x) { for(int i=first[x];i;i=nx[i]) { if(to[i] == par[x] || vis[to[i]] != clo) continue; par[to[i]] = x; node[to[i]] = extend(node[x], va[i]); dfs(to[i]); } } int run() { int now = root, len = strlen(s + 1); rep(i, 1, len) { // while(now && !tr[now][s[i] - 'a']) now = pre[now]; now = tr[now][s[i] - 'a']; } //cerr << now << endl; if(!now) return 0; access(now); splay(now); return val[now]; } int main() { //freopen("8.in","r",stdin); //freopen("8oo.out","w",stdout); //freopen("8oo_err","w",stderr); root = ++dfn; node[1] = root; read(); n = read(); clo++; rep(i, 2, n) { int u = read(), v = read(); char ch; cin >> ch; add(u, v, ch - 'a'); add(v, u, ch - 'a'); //cout << ch << endl; vis[u] = vis[v] = clo; } dfs(1); int q = read(); while(q--) { int opt = read(); if(opt == 1) printf("%lld\n", ans); else if(opt == 2) { int ri = read(), si = read(); clo++; rep(i, 2, si) { int u = read(), v = read(); char ch; cin >> ch; add(u, v, ch - 'a'); add(v, u, ch - 'a'); vis[u] = vis[v] = clo; } dfs(ri); } else if(opt == 3) { scanf("%s", s + 1); printf("%d\n", run()); } //int xo = 0; // rep(i, 1, n) xo ^= node[i]; //cerr << xo << endl; } }View Code
标签:ch,fa,Trie,DQS,int,tag,maxn,inline,4545 来源: https://www.cnblogs.com/Kong-Ruo/p/10626265.html