考虑一下,如果串B在串A中出现过,那么A的fail指针必定直接或间接指向B
那么我们可以把fail树建起来,那么就变成B代表的节点的子树里有多少节点属于A
然后这就是一个序列统计问题,直接用dfs序+树状数组可以维护
具体的操作就是,先把每一个点有关的询问给存起来,然后等到在trie树上一遍dfs,当dfs到这个串的结束节点说明所有有关这个串的节点都被遍历到(可以在遍历的时候顺便用树状数组维护序列和),然后对每一个询问查一下子树和即可
1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<queue> 6 #include<algorithm> 7 using namespace std; 8 const int N=100005; 9 int tot=1; 10 struct node{ 11 int num,type; 12 node(){} 13 node(int num,int type):num(num),type(type){} 14 }; 15 queue<node> q; 16 int ch[N][26],End[N],word,fa[N],fail[N],dis[N]; 17 inline int insert(int p,int c){ 18 if(ch[p][c]) return ch[p][c]; 19 ch[p][c]=++tot,fa[tot]=p;return tot; 20 } 21 inline int back(int p){return fa[p];} 22 inline void ed(int p){End[p]=++word,dis[word]=p;} 23 void build(){ 24 for(int i=0;i<26;++i) 25 if(ch[1][i]) 26 q.push(node(ch[1][i],i)),fail[ch[1][i]]=1; 27 while(!q.empty()){ 28 node now=q.front();q.pop(); 29 if(fail[now.num]!=1){ 30 int trail=fail[fa[now.num]]; 31 while(true){ 32 if(ch[trail][now.type]){trail=ch[trail][now.type];break;} 33 if(trail==1) break;trail=fail[trail]; 34 } 35 fail[now.num]=trail; 36 } 37 for(int i=0;i<26;++i) 38 if(ch[now.num][i]) 39 q.push(node(ch[now.num][i],i)); 40 } 41 } 42 int ver[N<<1],Next[N<<1],head[N],E=0; 43 inline void add(int u,int v){ 44 ver[++E]=v,Next[E]=head[u],head[u]=E; 45 } 46 int ver1[N],Next1[N],head1[N],edge1[N],E1=0; 47 inline void add1(int u,int v,int num){ 48 ver1[++E1]=v,Next1[E1]=head1[u],head1[u]=E1,edge1[E1]=num; 49 } 50 int c[N<<1]; 51 inline void addd(int x,int y){ 52 for(;x<=tot;x+=x&-x) c[x]+=y; 53 } 54 inline int sum(int x){ 55 int res=0; 56 for(;x;x-=x&-x) res+=c[x]; 57 return res; 58 } 59 int dfn[N],sz[N],cnt=0,ans[N]; 60 bool book[N]; 61 void dfsfail(int u){ 62 dfn[u]=++cnt,sz[u]=1,book[u]=true; 63 for(int i=head[u];i;i=Next[i]){ 64 int v=ver[i]; 65 if(!book[v]) dfsfail(v),sz[u]+=sz[v]; 66 } 67 } 68 void dfstrie(int u){ 69 addd(dfn[u],1); 70 if(End[u]){ 71 for(int i=head1[End[u]];i;i=Next1[i]){ 72 int v=ver1[i],x=dis[v]; 73 // printf("%d %d %d ",v,x,edge1[i]); 74 ans[edge1[i]]=sum(dfn[x]+sz[x]-1)-sum(dfn[x]-1); 75 } 76 } 77 for(int i=0;i<26;++i) 78 if(ch[u][i]) dfstrie(ch[u][i]); 79 addd(dfn[u],-1); 80 } 81 char s[N];int len,m,st; 82 int main(){ 83 // freopen("testdata.in","r",stdin); 84 scanf("%s",s+1); 85 len=strlen(s+1); 86 for(st=1;st<=len;++st) 87 if(s[st]!='B'&&s[st]!='P') break; 88 int p=insert(1,s[st]-'a'); 89 for(int i=st+1;i<=len;++i){ 90 if(s[i]=='B') p=back(p); 91 else if(s[i]=='P') ed(p); 92 else p=insert(p,s[i]-'a'); 93 } 94 scanf("%d",&m); 95 for(int i=1,u,v;i<=m;++i){ 96 scanf("%d%d",&u,&v); 97 add1(v,u,i); 98 } 99 build(); 100 for(int i=2;i<=tot;++i) 101 add(fail[i],i),add(i,fail[i]); 102 dfsfail(1),dfstrie(1); 103 for(int i=1;i<=m;++i) printf("%d ",ans[i]); 104 return 0; 105 }