# @bzoj - 3881@ [Coci2015]Divljak

## @description@

Alice有n个字符串S_1,S_2...S_n，Bob有一个字符串集合T，一开始集合是空的。

“1 P”，Bob往自己的集合里添加了一个字符串P。
“2 x”，Alice询问Bob，集合T中有多少个字符串包含串S_x。（我们称串A包含串B，当且仅当B是A的子串）
Bob遇到了困难，需要你的帮助。

Input

Output

Sample Input
3
a
bc
abc
5
1 abca
2 1
1 bca
2 2
2 3
Sample Output
1
2
1

HINT
1 <= n,q <= 100000；
Alice和Bob拥有的字符串长度之和各自都不会超过 2000000；

## @accepted code@

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 100000;
const int MAXS = 2000000;
struct BIT{
int tree[MAXS + 5], tot;
int lowbit(int x) {return x & (-x);}
void update(int x, int k) {
for(int i=x;i<=tot;i+=lowbit(i))
tree[i] += k;
//		printf(". %d %d\n", x, k);
}
int sum(int x) {
int ret = 0;
for(int i=x;i;i-=lowbit(i))
ret += tree[i];
return ret;
}
}T;
struct Graph{
struct edge{
edge *nxt;
int to;
}edges[MAXS + 5], *adj[MAXS + 5], *ecnt;
Graph() {ecnt = &edges[0];}
void addedge(int u, int v) {
edge *p = (++ecnt);
//		printf("! %d %d\n", u, v);
}
int siz[MAXS + 5], dep[MAXS + 5], hvy[MAXS + 5], fa[MAXS + 5];
void dfs1(int x, int f) {
siz[x] = 1; fa[x] = f; dep[x] = dep[f] + 1; hvy[x] = 0;
if( p->to == f ) continue;
dfs1(p->to, x);
siz[x] += siz[p->to];
if( siz[p->to] > siz[hvy[x]] )
hvy[x] = p->to;
}
}
int tid[MAXS + 5], dfn[MAXS + 5], top[MAXS + 5], dcnt;
void dfs2(int x, int tp) {
top[x] = tp; dfn[++dcnt] = x; tid[x] = dcnt;
if( hvy[x] ) dfs2(hvy[x], tp);
if( p->to == fa[x] || p->to == hvy[x] ) continue;
dfs2(p->to, p->to);
}
}
void build() {dfs1(1, 0); dfs2(1, 1); T.tot = dcnt;}
int lca(int u, int v) {
while( top[u] != top[v] ) {
if( dep[top[u]] < dep[top[v]] ) swap(u, v);
u = fa[top[u]];
}
if( dep[u] < dep[v] ) swap(u, v);
return v;
}
}G;
bool cmp(int x, int y) {return G.tid[x] < G.tid[y];}
struct ACM{
struct node{int ch[26], fail;}nd[MAXS + 5];
int root, ncnt;
ACM() {root = ncnt = 0;}
int lenS = strlen(S), nw = root;
for(int i=0;i<lenS;i++) {
if( !nd[nw].ch[S[i] - 'a'] )
nd[nw].ch[S[i] - 'a'] = (++ncnt);
nw = nd[nw].ch[S[i] - 'a'];
}
return nw + 1;
}
void link(int a, int b) {
nd[b].fail = a, G.addedge(a + 1, b + 1);
}
int arr[MAXS + 5];
void build() {
int hd = 1, tl = 0;
for(int i=0;i<26;i++)
if( nd[root].ch[i] ) {
arr[++tl] = nd[root].ch[i];
}
else nd[root].ch[i] = root;
while( hd <= tl ) {
int f = arr[hd++];
for(int i=0;i<26;i++) {
if( !nd[f].ch[i] )
nd[f].ch[i] = nd[nd[f].fail].ch[i];
else {
arr[++tl] = nd[f].ch[i];
}
}
}
}
void modify(char *S) {
int rt = root; int lenS = strlen(S);
for(int i=0;i<lenS;i++) {
rt = nd[rt].ch[S[i] - 'a'];
arr[i] = rt + 1;
//			printf("? %d %d\n", arr[i], rt - pl + 1);
}
sort(arr, arr + lenS, cmp);
for(int i=0;i<lenS;i++) T.update(G.tid[arr[i]], 1);
for(int i=1;i<lenS;i++) T.update(G.tid[G.lca(arr[i-1], arr[i])], -1);
}
}ac;
char S[MAXS + 5];
int id[MAXN + 5];
int main() {
int n, q; scanf("%d", &n);
for(int i=1;i<=n;i++) {
scanf("%s", S);
}
ac.build(), G.build();
scanf("%d", &q);
for(int i=1;i<=q;i++) {
int op; scanf("%d", &op);
if( op == 1 ) {
scanf("%s", S);
ac.modify(S);
}
else {
int x; scanf("%d", &x);
printf("%d\n", T.sum(G.tid[id[x]] + G.siz[id[x]] - 1) - T.sum(G.tid[id[x]] - 1));
}
}
}

## @details@

posted @ 2019-08-16 09:47  Tiw_Air_OAO  阅读(132)  评论(0编辑  收藏  举报