BZOJ 3881: [Coci2015]Divljak
首先建出 \(S\) 的AC自动机和fail树
要使T中每个字符串只被计算一次,那么就得在dfs序相邻的两个节点的lca处-1
#include <bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define pii pair<ll, int>
#define lp p << 1
#define rp p << 1 | 1
#define mid ((l + r) >> 1)
#define lowbit(i) ((i) & (-i))
#define ll long long
#define db double
#define rep(i,a,b) for(int i=a;i<b;i++)
#define per(i,a,b) for(int i=b-1;i>=a;i--)
#define Edg int ccnt=1,head[N],to[N*2],ne[N*2];void addd(int u,int v){to[++ccnt]=v;ne[ccnt]=head[u];head[u]=ccnt;}void add(int u,int v){addd(u,v);addd(v,u);}
#define Edgc int ccnt=1,head[N],to[N*2],ne[N*2],c[N*2];void addd(int u,int v,int w){to[++ccnt]=v;ne[ccnt]=head[u];c[ccnt]=w;head[u]=ccnt;}void add(int u,int v,int w){addd(u,v,w);addd(v,u,w);}
#define es(u,i,v) for(int i=head[u],v=to[i];i;i=ne[i],v=to[i])
const int MOD = 20170408;
void M(int &x) {if (x >= MOD)x -= MOD; if (x < 0)x += MOD;}
int qp(int a, int b = MOD - 2) {int ans = 1; for (; b; a = 1LL * a * a % MOD, b >>= 1)if (b & 1)ans = 1LL * ans * a % MOD; return ans % MOD;}
int gcd(int a, int b) { while (b) { a %= b; std::swap(a, b); } return a; }
const int N = 2e6 + 7;
int ch[N][26], fail[N], dep[N], in[N], out[N], root = 1, tol = 1, n, mp[N], dfn;
Edg
char s[N];
int fa[N], top[N], sz[N], son[N];
void ins(char *s, int index) {
int len = strlen(s);
int cur = root;
rep (i, 0, len) {
int c = s[i] - 'a';
if (!ch[cur][c]) ch[cur][c] = ++tol;
cur = ch[cur][c];
}
mp[index] = cur;
}
void build() {
static int que[N];
int l = 0, r = 0;
rep (c, 0, 26) {
if (!ch[root][c]) ch[root][c] = root;
else que[r++] = ch[root][c], fail[ch[root][c]] = root;
}
while (l ^ r) {
int cur = que[l++];
rep (c, 0, 26) {
if (!ch[cur][c]) ch[cur][c] = ch[fail[cur]][c];
else que[r++] = ch[cur][c], fail[ch[cur][c]] = ch[fail[cur]][c];
}
}
rep (i, root + 1, tol + 1) add(i, fail[i]);
}
void dfs(int u, int f = 0) {
dep[u] = dep[f] + 1;
in[u] = ++dfn;
fa[u] = f;
sz[u] = 1;
es (u, i, v) {
if (v == f) continue;
dfs(v, u);
sz[u] += sz[v];
if (sz[v] > sz[son[u]]) son[u] = v;
}
out[u] = dfn;
}
void dfs2(int u, int tp) {
top[u] = tp;
if (!son[u]) return;
dfs2(son[u], tp);
es (u, i, v) if (v != fa[u] && v != son[u]) dfs2(v, v);
}
int Lca(int u, int v) {
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) std::swap(u, v);
u = fa[top[u]];
}
return dep[u] < dep[v] ? u : v;
}
bool cmp(int a, int b) { return in[a] < in[b]; }
int tree[N];
void edit(int x, int v) { for (int i = x; i <= dfn; i += lowbit(i)) tree[i] += v; }
int query(int x) { int ans = 0; for (int i = x; i; i -= lowbit(i)) ans += tree[i]; return ans; }
void solve(char *s) {
int len = strlen(s);
static int st[N];
int top = 0, cur = root;
rep (i, 0, len) {
cur = ch[cur][s[i] - 'a'];
st[++top] = cur;
}
std::sort(st + 1, st + 1 + top, cmp);
top = std::unique(st + 1, st + 1 + top) - st - 1;
rep (i, 1, top + 1) {
edit(in[st[i]], 1);
if (i != top) edit(in[Lca(st[i], st[i + 1])], -1);
}
}
int main() {
scanf("%d", &n);
rep (i, 1, n + 1) {
scanf("%s", s);
ins(s, i);
}
build();
dfs(root);
dfs2(root, root);
int q;
scanf("%d", &q);
while (q--) {
int opt;
scanf("%d", &opt);
if (opt == 1) {
scanf("%s", s);
solve(s);
} else {
int x;
scanf("%d", &x);
printf("%d\n", query(out[mp[x]]) - query(in[mp[x]] - 1));
}
}
return 0;
}