Test instructions: Given three actions: 1, add a character C 2 at the end of the current string, delete a character 3 at the end of the current string, record the current string, and label it. Given the n group of queries, each group of queries is asked to answer the number of occurrences of the X string in the first Y string.
Exercises
First, build trie with the following rule, set the current node to T, and the end of the I string in the trie position is mark[i]:
1. Insert operation: see if T has c this son, there is t=t->child[c], otherwise t->child[c]=newnode,t=t->child[c]
2. Delete operation: T=t->father
3, marking operation: mark[i]=t,i++
Build the Fail pointer after trie, then for each query (x, y), the answer is trie from mar[y] to the root of the path, how many nodes after one or more fail pointer transfer can reach MARK[X].
Considering that the fail pointer is all from bottom to top and each node has a degree of 1, so we built the inverse fail tree according to the inverse fail pointer, then the question becomes, in the mark[x of the inverse fail tree, how many nodes are in the mark[y] to the root path, The subtree is run out of Dfs sequence. Then we go offline, put all y same queries together, use a tree array to maintain a string that ends with a point, and reread all the actions:
1. Insert operation: +1,t=t->child[s[i]-' A ' for the value of the node where T is located on the DFS order
2. Delete operation: The value of the node where T is located on the DFS sequence -1,t=t->f
3, label operation: Query T about the answer of the inquiry
#include <queue>#include<vector>#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>using namespacestd;#defineLowbit (x) (x& (×))Const intmaxk= -;Const intmaxn=100000+2;structhash{intX,id; HASH*Next; Hash () {} hash (int_x,int_id,hash *_next): X (_x), id (_id), Next (_next) {}}*TABLE[MAXN],MEM[MAXN];structtrie{intId,mark; Trie*child[maxk],*f,*fail; Vector<trie *>next;}*Root;intm,n=1, CNT,ANS[MAXN],BIT[MAXN],L[MAXN],R[MAXN];CharS[maxn];queue<trie *>Q; Trie*newnode (Trie *G) {Trie*x=NewTrie; memset (x,0,sizeof(Trie)); X->f=F; returnx;}voidGet_fail (Trie *&x) { for(intI=0; i<maxk;i++) if(x->Child[i]) {x->child[i]->fail=x,q.push (x->Child[i]); X->next.push_back (x->Child[i]); } Trie*p,*T; while(!Q.empty ()) {T=q.front (), Q.pop (), n++; for(intI=0; i<maxk;i++) if(t->Child[i]) {P=t->fail; while(P!=x &&!p->child[i]) p=p->fail; if(P->child[i]) p=p->Child[i]; T->child[i]->fail=p,p->next.push_back (t->Child[i]); Q.push (t-Child[i]); } ElseT->child[i]=t->fail->Child[i]; }}voidDFS (Trie *&x) {x->id=++CNT; if(X->mark) l[x->mark]=CNT; for(intI=0; I<x->next.size (); i++) DFS (x->Next[i]); if(X->mark) r[x->mark]=CNT;}intSum (intp) { intret=0; while(p) ret+=bit[p],p-=lowbit (P); returnret;}voidADD (intPintx) { while(p<=n) bit[p]+=x,p+=lowbit (P);}intMain () {scanf ("%s%d",s,&M); for(intI=1, x,y;i<=m;i++) {scanf ("%d%d",&x,&y); Table[y]=& (mem[cnt++]=HASH (X,i,table[y])); } Trie*t=root=newnode (0); for(intI=0, j=0; s[i];i++) if(s[i]=='P') t->mark=++J; Else if(s[i]=='B') t=t->F; Else{ if(!t->child[s[i]-'a']) t->child[s[i]-'a']=NewNode (t); T=t->child[s[i]-'a']; } CNT=0; Get_fail (Root), DFS (root); T=Root; for(intI=0; s[i];i++) if(s[i]=='P') for(HASH *p=table[t->mark];p;p=p->next) Ans[p->id]=sum (R[p->x])-sum (l[p->x]-1); Else if(s[i]=='B') Add (t->id,-1),t=t->F; Elset=t->child[s[i]-'a'],add (T->id,1); for(intI=1; i<=m;i++) printf ("%d\n", Ans[i]); return 0;}
View Code
BZOJ2434 NOI2011 Ali Typewriter ac automata + tree-like array +dfs sequence