Description
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:
• Enter lowercase letters, which are added to a groove in the typewriter (the letter is added to the end of the groove).
• Press the ' B ' button and the last letter in the typewriter's groove disappears.
• Press the ' P ' button and the typewriter will print all the existing letters in the groove on the paper and wrap them, 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?
Solution
Actually 1 a"but read the puzzle"
Query how many times x appears in Y, that is, how many nodes of Y can jump to the tail node of x by fail
But this is too violent, so let's build a fail tree (the reverse side of fail, pointed to the original node by the fail pointer)
The number of nodes that are converted to the Y node of the query x that can be reached from the fail tree
It can then be done by DFS sequence and tree array.
Offline, for the same y one-time processing, mark out all Y nodes, and query the number of occurrences of Y nodes in each x's subtree
#include <iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<queue>#defineMAXN 100005using namespacestd;intM,SZ,ROOT,POS[MAXN],inch[MAXN], out[maxn],dfn_clock=0, C[MAXN],ANS[MAXN],DFN[MAXN];inthead1[maxn],head2[maxn],cnt1=0, cnt2=0;structnode2{intNext,to;} E1[MAXN],E2[MAXN];voidAddedge1 (intUintv) {e1[++cnt1].next=Head1[u]; Head1[u]=Cnt1; E1[cnt1].to=v;}voidAddedge2 (intUintv) {e2[++cnt2].next=Head2[u]; Head2[u]=Cnt2; E2[cnt2].to=v;} CharS[MAXN];structnode1{intnext[ -],par,fail;} TRIE[MAXN];intNewNodeintf) {trie[++sz].fail=0; Trie[sz].par=F; memset (Trie[sz].next,0,sizeof(Trie[sz].next)); returnsz;}voidInsert () {sz=0, Root=newnode (0); intI=0, p=root,_clock=0; while(S[i]) {if(s[i]=='B') P=Trie[p].par; Else if(s[i]=='P') pos[++_clock]=p; Else { intidx=s[i]-'a'; if(!trie[p].next[idx]) trie[p].next[idx]=NewNode (P); P=Trie[p].next[idx]; } I++; }}queue<int>Q;voidbuild () {Q.push (root); while(!Q.empty ()) { intp=Q.front (); Q.pop (); for(intI=0;i< -; i++) { intt=Trie[p].fail; while(T&&!trie[t].next[i]) t=Trie[t].fail; if(Trie[p].next[i]) {Trie[trie[p].next[i]].fail=t?Trie[t].next[i]:root; Q.push (Trie[p].next[i]); } ElseTrie[p].next[i]=t?Trie[t].next[i]:root; } }}voidDfsintu) { if(Dfn[u])return; ++Dfn_clock; inch[u]=dfn[u]=Dfn_clock; for(intI=head1[u];~i;i=e1[i].next) DFS (e1[i].to); out[u]=Dfn_clock;}intLowbit (intx) {returnx& (-x);}voidAddintXintp) { while(p<=sz+1) {C[p]+=x; P+=lowbit (P); }}intQueryintp) { intres=0; while(p>0) {res+=C[p]; P-=lowbit (P); } returnRes;}voidsolve () {intI=0, p=root,_clock=0; while(S[i]) {if(s[i]=='B') Add (-1, Dfn[p]), p=Trie[p].par; Else if(s[i]=='P') { ++_clock; for(intj=head2[_clock];~j;j=E2[j].next) { intt=e2[j].to; ANS[J]=query ( out[Pos[t]]) -query (inch[pos[t]]-1); } } Else { intidx=s[i]-'a'; P=Trie[p].next[idx]; Add (1, Dfn[p]); } I++; }}intMain () {memset (Head1,-1,sizeof(HEAD1)); memset (Head2,-1,sizeof(head2)); scanf ("%s", s); Insert (), build (); for(intI=1; i<=sz;i++) Addedge1 (trie[i].fail,i); scanf ("%d",&m); for(intI=1; i<=m;i++) { intx, y; scanf ("%d%d",&x,&y); Addedge2 (Y,X); } DFS (0); Solve (); for(intI=1; i<=m;i++) printf ("%d\n", Ans[i]); return 0;}
[Bzoj 2434] [Noi2011] Ali Typewriter (AC automaton + Tree array +dfs sequence)