This question is really God, a lot of practical skills. First of all, it must be the output of each string when the model string to build the automaton, if a string copied out and then inserted into a very slow ... We use the method of inserting the pattern string on the automaton, the initial time in 0, the new addition of a character would like to crawl (or new), maintain a father pointer, delete the time can climb up, so that can be built out of O (n).
Again, consider asking questions, each time the string out and put it in the automatic machine run again obviously too slow. A thing called the Fail tree is needed here, which is to use the fail pointer as a tree for the side. For example, fail (i) =j, then I on the fail tree's parent node is J. For each query, if the X-string appears in the Y-string, then the next pointer on the path to the Y-string node is the X-string node, which is placed on the fail tree, and the answer to the query (x, y) is the number of nodes on the China in the root-to-y node of the fail, see subtrees, Consider using DFS ordering to resolve: Hook up all the queries like a linked list to the respective Y-string nodes, and then simulate the beginning of the insertion process, and each crawl down to a node will have it in the Dfs order at the left edge of +1, each up and down the left edge of a node in the DFS order-1, Each time you crawl to a danger node, the query for all of the nodes is resolved, and a tree-like array is used to maintain the prefix.
#include <iostream> #include <cstdio> #include <memory.h> #define N 100005using namespace Std;char s[n] ; struct Edge{int e,next;} Ed[n];struct query{int E,next,xu;} Q[n];int i,j,ne=0,x,y,t=0,nq=0,n,m,a[n][27],head[n],que[n],next[n],fa[n],l[n],r[n],c[n*2],g[n],ans[n],pos[n];// CNT is the number of strings, ND is the AC automaton, NE is the number of fail trees, NQ is the number of links to query the edge of void inse (int s,int e) {ed[++ne].e=e;ed[ne].next=g[s];g[s]=ne;} void insq (int x,int y,int i) {q[++nq].e=x;q[nq].xu=i;q[nq].next=head[y];head[y]=nq;} int lowbit (int x) {return x&-x;} void Add (int x,int k) {for (int i=x;i<=t;i+=lowbit (i)) c[i]+=k;} int sum (int x) {int ans=0;for (int i=x;i;i-=lowbit (i)) Ans+=c[i];return ans;} void init () {int I,now=1,cnt=0,nd=1;memset (a,0,sizeof (a)); Memset (C,0,sizeof (c)); Memset (Head,0,sizeof (head)); memset (G,0,sizeof (g)); N=strlen (s); Fa[1]=0;for (i=0;i<26;i++) a[0][i]=1;for (i=0;i<n;i++) if (s[i]== ' P ') pos[++ Cnt]=now;else if (s[i]== ' B ') now=fa[now];else{if (!a[now][s[i]-' a ']) {a[now][s[i]-' a ']=++nd;fa[nd]=now;} Now=a[now][s[i]-' a '];}} void bUild () {next[1]=0;inse (0,1); int Head=1,tail=1,get,k,i;que[1]=1;while (head<=tail) {get=que[head++];for (i=0;i <26;i++) if (A[get][i]) {k=next[get];while (!a[k][i]) k=next[k];k=a[k][i];next[a[get][i]]=k;inse (K,a[get][i]); Que[++tail]=a[get][i];}}} void Dfs (int x) {l[x]=++t;for (int j=g[x];j;j=ed[j].next) DFS (ED[J].E); r[x]=++t;} void Solve () {int Now=1,cnt=0,i,j;add (l[1],1), for (i=0;i<n;i++) if (s[i]== ' P ') {cnt++;for (j=head[now];j;j=q[j]. Next) Ans[q[j].xu]=sum (R[Q[J].E])-sum (l[q[j].e]-1);} else if (s[i]== ' B ') Add (l[now],-1), Now=fa[now];else now=a[now][s[i]-' a '],add (l[now],1);} int main () {freopen ("2434.in", "R", stdin), scanf ("%s", s), scanf ("%d", &m), Init (); build ();d FS (0); for (i=1;i<=m; i++) {scanf ("%d%d", &x,&y); insq (pos[x],pos[y],i);} Solve (); for (i=1;i<=m;i++) printf ("%d\n", Ans[i]);}
[BZOJ2434] NOI2011 Ali's Typewriter | AC Automaton |fail Tree | tree-like array