**bzoj3881 [Coci2015]divljak**
**Original title address** : http://www.lydsy.com/JudgeOnline/problem.php?id=3881

**Test Instructions:**

Alice has n strings of s1,s2 ... Sn s 1, s 2 ... S n S_1,s_2...s_n,bob has a string set T, and the beginning of the collection is empty.

Then there are the Q operations, which take two forms:

"1 P", Bob adds a string P to his own collection.

"2 X", Alice asks Bob how many strings in the collection T contain the string Sx S x s_x. (We call string A contains string B, when and only if B is a substring of a)

Bob is in trouble and needs your help.

**Data Range**

1 <= n,q <= 100000

Alice and Bob have no more than 2000000 of the string lengths of each.

Strings are made up of lowercase English letters.

The **following:**

The paper's Inner puzzle:

Good question. It would be nice to think of an AC automaton built on S.

A contains string b how many times, is a on the AC automaton each node, how many in the B end node in the Fail tree subtree.

So:

1 operation is equivalent to a new color of these nodes of P (color does not overlap can coexist)

2 operation equivalent to query Sx S x s_x end node fail tree subtree color kind.

Is the classic sort by DFS order, u++,v--,lca (u,v)--the operation of each query subtree weights and, with a tree-like array to maintain.

It is not necessary to add p to the AC automaton, and finally to the node of S, directly on the AC automaton built by the s set to run, to pass the string operation can be.

Multiplying LCA will be card, write tree chain split or LCT.

** Code: **

#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <
Queue> using namespace std;
const int n=2000003;
Queue<int> Q;
int n,q,ch[n][26],fail[n],root=1,tail=1,s[n],cnt=0,c[n];
int head[n],to[n],nxt[n],num=0,pos[n],size[n],son[n],top[n],in[n],out[n],inc=0,dep[n],fa[n];
Char Str[n]; BOOL CMP (const int &A,CONST int &b) {return in[a]<in[b];} void ADD (int x,int d) {for (int i=x;i<=inc;i=i+ (i&am
p; (i))) C[i]+=d;} inline int query (int x) {int ret=0; for (Int. i=x;i;i-= (i& (i)) ret+=c[i]; return ret;} void build (int u,int v) {nu
m++;
To[num]=v;
Nxt[num]=head[u];
Head[u]=num;
} inline int Insert () {int len=strlen (str); int tmp=root;
for (int i=0;i<len;i++) {int c=str[i]-' a ';
if (!ch[tmp][c]) Ch[tmp][c]=++tail;
TMP=CH[TMP][C];
} return TMP; } void Getfail () {for (int i=0;i<26;i++) if (Ch[root][i]) fail[ch[root][i]]=root,build (Root,ch[root][i]), Q.push (cH[root][i]);
else Ch[root][i]=root; while (! Q.empty ()) {int Top=q.front ();
Q.pop ();
for (int i=0;i<26;i++) {if (!ch[top][i]) ch[top][i]=ch[fail[top]][i];
else {int u=ch[top][i];
Fail[u]=ch[fail[top]][i];
Build (Fail[u],u);
Q.push (U); }}}} void dfs1 (int u,int f) {size[u]=1; dep[u]=dep[f]+1;
Fa[u]=f;
for (int i=head[u];i;i=nxt[i]) {int v=to[i]; DFS1 (V,u);
SIZE[U]+=SIZE[V];
if (Size[v]>size[son[u]]) son[u]=v;
}} void dfs2 (int u,int tp) {top[u]=tp; inc++; in[u]=inc;
if (Son[u]) DFS2 (SON[U],TP);
for (int i=head[u];i;i=nxt[i]) {int v=to[i];
if (V==son[u]) continue;
DFS2 (V,V);
} out[u]=inc;
} int Getlca (int u,int v) {while (Top[u]!=top[v]) {if (Dep[top[u]]<dep[top[v]) swap (U,V);
U=fa[top[u]]; } return dep[u]≪dep[v]?u:v;
} void Add () {int len=strlen (str); int tmp=root; cnt=0;
for (int i=0;i<len;i++) {int c=str[i]-' a ';
TMP=CH[TMP][C];
s[++cnt]=tmp; } sort (s+1,s+cnt+1,cmp);
int last=0;
for (int i=1;i<=cnt;i++) {if (s[i]==last) continue;
ADD (in[s[i]],1);
if (last!=0) ADD (In[getlca (last,s[i))],-1);
Last=s[i];
}} int main () {scanf ("%d", &n);
for (int i=1;i<=n;i++) {scanf ("%s", str);
Pos[i]=insert ();
} getfail (); DFS1 (a);
DFS2 (a);
scanf ("%d", &q);
while (q--) {int opt,x;
scanf ("%d", &opt);
if (opt==1) scanf ("%s", str), add ();
else {scanf ("%d", &x);
printf ("%d\n", Query (Out[pos[x])-query (in[pos[x]]-1));
}} return 0;
}