Description
Ali like to collect all kinds of strange things, he recently Amoy to an old-fashioned typewriter. There are only 28 keys on the typewriter, with 26 lowercase English letters and ' B ' and ' P ' two letters printed respectively.
The ALI study found that the typewriter worked like this:
L Enter lowercase letters and the letter is added to a groove in the typewriter (the letter is added to the end of the groove).
L PRESS the ' B ' button and the last letter in the typewriter groove disappears.
L PRESS the ' P ' button and the typewriter will print all the existing letters in the groove and wrap them on the paper, but the letters in the groove will not disappear.
For example, Ali input APAPBBP, the characters printed on the paper are as follows:
A
Aa
Ab
We numbered the printed string on the paper from 1 onwards to N. Typewriter has a very interesting function, in the typewriter hidden a small keyboard with a number, on the keypad input two number (x, y) (where 1≤x,y≤n), the typewriter will show the first x printed string in the first number of printed strings in the occurrence of how many times.
Ali found this feature was very excited, he wanted to write a program to complete the same function, can you help him?
Input
The first line of input contains a string that gives all the characters of the beaver input in the order of Ali input.
The second line contains an integer m, which indicates the number of queries.
The next M-line describes all the queries entered by the keypad. Where line I contains two integers x, y, which indicates that I inquired for (x, y).
Output
Output m line, where line I contains an integer representing the answer to the I query.
Sample InputAPAPBBP
3
1 2
1 3
2 3
Sample Output2
1
0HINT
1<=n<=10^5
1<=m<=10^5 input total length <=10^5----------------------------------------
The fail tree is one such thing: Connect the fail pointer of the AC automaton to a tree (the root node is virtual node 0).
What good is this? Match to find all matching locations along the fail tree:
voidFindChar*s) { intj=0, C; for(intI=0; s[i]!=' /'; i++) {C=s[i]-'a'; while(J&&!ch[j][c]) j=F[j]; for(intT=J;T;T=F[T])if(Val[t]) cnt[val[t]]++; }}
View Code
That is, for a node C from root (0) to the C-linked string (template string), a node v from root (0) to the V-linked string (matching string), the number of matching strings in the template string is the root->c path of the node on the number of nodes on the node V in the subtree.
So we just need to maintain the DFS sequence.
Then this problem is the bottom of the way:
First build the AC Automaton's fail tree to derive the Dfs sequence, and derive the time of each node in and out L[x],r[x], consider such a violent
For a query of x, Y, each node of the root-y on the automaton, whether or not the fail pointer will go to the end of X, if it can answer +1.
Then it becomes in the fail tree, how many of the nodes in the root-y on the query automaton are in the subtree of X.
Just go through the automaton again and walk to a node Y, then 1-l[y] +1. Resolve to ask X, Y (the same linked list of y), that is, query l[x] to r[x] and. When encountering a B 1-l[y] all-1.
Just a tree-like array for addition and subtraction and interval summation
Casually write, unexpectedly in Bzoj on the RANK1, I am very happy (<---This goods two die kneeling still here to die)
#include <cstdio>#include<cctype>#include<cstring>#include<queue>#include<algorithm>using namespaceStd;inlineintRead () {intx=0, f=1;CharC=GetChar (); for(;! IsDigit (c); C=getchar ())if(c=='-') f=-1; for(; IsDigit (c); C=getchar ()) x=x*Ten+c-'0'; returnx*F;}voidPrintintx) { if(!x) {Putchar ('0');p Utchar ('\ n');return;} intlen=0, buf[ the]; while(x) buf[++len]=x%Ten, x/=Ten; for(inti=len;i;i--) Putchar (buf[i]+'0'); Putchar ('\ n');}Const intmaxn=200010;intch[maxn][ -],fa[maxn],f[maxn],pos[maxn],id,sz;voidInsertChar*s) { intj=0, C; for(intI=0; s[i];i++) {C=s[i]-'a'; if(s[i]=='P') pos[++id]=J; Else if(s[i]=='B') j=Fa[j]; Else { if(!ch[j][c]) ch[j][c]=++sz,fa[sz]=J; J=Ch[j][c]; }}}queue<int>Q;voidGetfail () { for(intC=0;c< -; C + +)if(ch[0][C]) Q.push (ch[0][c]); while(!Q.empty ()) { intu=Q.front (), V;q.pop (); for(intC=0;c< -; C + +)if(v=Ch[u][c]) {Q.push (v);intj=F[u]; while(J&&!ch[j][c]) j=F[j]; F[V]=Ch[j][c]; } }}intfirst[maxn],next[maxn],to[maxn],e;voidAddedge (intUintV) {to[++e]=v;next[e]=first[u];first[u]=e;}intl[maxn],r[maxn],cnt;voidDfsintx) {L[x]=++CNT; for(intI=first[x];i;i=Next[i]) DFS (to[i]); R[X]=++CNT;}intSUMV[MAXN];voidAddintXintV) { for(; x<=cnt;x+=x&-x) sumv[x]+=v;}intSumintx) {intret=0; for(; x;x-=x&-x) ret+=sumv[x];returnret;}structQuery {intNext,v;} Q[MAXN];intFIRSTQ[MAXN],ANS[MAXN];voidSolveChar*s) { intj=0, C;add (L[j],1); id=0; for(intI=0; s[i];i++) {C=s[i]-'a'; if(s[i]=='P') {ID++; for(intx=firstq[id];x;x=Q[x].next) { intv=POS[Q[X].V]; ANS[X]=sum (R[v])-sum (l[v]-1); } } Else if(s[i]=='B') Add (l[j],-1), j=Fa[j]; ElseJ=ch[j][c],add (L[j],1); }}CharS[MAXN];intMain () {scanf ("%s", s); insert (s); Getfail (); for(intI=1; i<=sz;i++) Addedge (f[i],i); DFS (0); intm=read (); for(intI=1; i<=m;i++) { intX=read (), y=read (); Q[I].V=x; q[i].next=firstq[y];firstq[y]=i; } solve (s); for(intI=1; i<=m;i++) print (ans[i]); return 0;}
View Code
NOI2011 Ali's typewriter (fail tree +dfs sequence)