1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define M 100008 5 using namespace std; 6 char ch[M]; 7 int cnt=1,pos[M],now,fa[M],fail[M],q[M],head[M],next[M],u[M],cnt1,m,n; 8 int a[M][26],head1[M],next1[M],u1[M],T,l[M],r[M],an[M],su[2*M]; 9 void build() 10 { 11 int h=0,t=1; 12 q[1]=1; 13 for(;h<t;) 14 { 15 int p=q[++h]; 16 for(int i=1;i<=26;i++) 17 if(a[p][i]) 18 { 19 int now=fail[p]; 20 q[++t]=a[p][i]; 21 for(;!a[now][i];now=fail[now]); 22 fail[a[p][i]]=a[now][i]; 23 } 24 } 25 return; 26 } 27 void jia(int a1,int a2) 28 { 29 cnt1++; 30 u[cnt1]=a2; 31 next[cnt1]=head[a1]; 32 head[a1]=cnt1; 33 return; 34 } 35 void dfs(int a1) 36 { 37 l[a1]=++T; 38 for(int i=head[a1];i;i=next[i]) 39 dfs(u[i]); 40 r[a1]=++T; 41 } 42 int xun(int a1) 43 { 44 int sum=0; 45 for(int i=a1;i;i-=i&-i) 46 sum+=su[i]; 47 return sum; 48 } 49 void add(int a1,int a2) 50 { 51 for(int i=a1;i<=T;i+=i&-i) 52 su[i]+=a2; 53 } 54 int main() 55 { 56 scanf("%s",ch+1); 57 now=1; 58 n=strlen(ch+1); 59 for(int i=1;i<=n;i++) 60 if(ch[i]=='P') 61 { 62 pos[0]++; 63 pos[pos[0]]=now; 64 } 65 else if(ch[i]=='B') 66 now=fa[now]; 67 else 68 { 69 if(!a[now][ch[i]-96]) 70 { 71 cnt++; 72 a[now][ch[i]-96]=cnt; 73 fa[cnt]=now; 74 } 75 now=a[now][ch[i]-96]; 76 } 77 for(int i=1;i<=26;i++) 78 a[0][i]=1; 79 build(); 80 for(int i=1;i<=cnt;i++) 81 jia(fail[i],i); 82 scanf("%d",&m); 83 for(int i=1;i<=m;i++) 84 { 85 int x,y; 86 scanf("%d%d",&x,&y); 87 u1[i]=x; 88 next1[i]=head1[y]; 89 head1[y]=i; 90 } 91 dfs(1); 92 now=1; 93 pos[0]=0; 94 for(int i=1;i<=n;i++) 95 if(ch[i]=='P') 96 { 97 pos[0]++; 98 for(int i=head1[pos[0]];i;i=next1[i]) 99 an[i]=xun(r[pos[u1[i]]])-xun(l[pos[u1[i]]]-1); 100 } 101 else if(ch[i]=='B') 102 { 103 add(l[now],-1); 104 now=fa[now]; 105 } 106 else 107 { 108 now=a[now][ch[i]-96]; 109 add(l[now],1); 110 } 111 for(int i=1;i<=m;i++) 112 printf("%d\n",an[i]); 113 return 0; 114 }
AC自动机 根据dfs序建立fail树(就是将失败指针反向),每次查询x子树中有多少y的节点。