询问x串在y串中出现次数,就是有多少y串的节点能顺着fail边跑到x的终止节点。所以建出fail树,求end[x] 为根的子树中有多少y的节点。
这个可以离线询问,用树状数组维护。
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define maxn 200005
using namespace std;
void read(int &a)
{
a=0;char c=getchar();
while(c<'0'||c>'9')c=getchar();
while(c>='0'&&c<='9')
{
a*=10;a+=c-'0';
c=getchar();
}
}
int c[maxn];
int N;
int low(int x)
{return (x&(-x));}
void add(int x,int d)
{
while(x<=N)
{
c[x]+=d;
x+=low(x);
}
}
int ask(int x)
{
int ans=0;
while(x>=1)
{
ans+=c[x];
x-=low(x);
}
return ans;
}
struct QUE{int x,y,id;}q[maxn];
bool cmp(QUE A,QUE B)
{return A.y<B.y;}
int ANS[maxn];
char s[maxn];
int T,fa[maxn];
struct E{int to,nxt;}b[maxn<<1];
int id[maxn],fst[maxn],tot;
void ins(int f,int t)
{
b[++tot]=(E){t,fst[f]};fst[f]=tot;
b[++tot]=(E){f,fst[t]};fst[t]=tot;
}
int dfn[maxn],dfs_c;
int in[maxn],out[maxn];
void dfs(int x)
{
dfn[++dfs_c]=x;
in[x]=dfs_c;
for(int i=fst[x];i;i=b[i].nxt)
{
int v=b[i].to;
if(!in[v]) dfs(v);
}
out[x]=dfs_c;
}
struct Trie
{
int val[maxn];
int ch[maxn][30],cnt;
int lst[maxn],fail[maxn];
void insert()
{
int p=0;
int n=strlen(s+1);
for(int i=1;i<=n;i++)
{
if(s[i]>='a'&&s[i]<='z')
{
int c=s[i]-'a'+1;
if(!ch[p][c])
{
ch[p][c]=++cnt;
fa[ch[p][c]]=p;
}
p=ch[p][c];
}
else if(s[i]=='B')p=fa[p];
else id[++T]=p;
}
}
queue<int> Q;
void build()
{
for(int i=1;i<=26;i++)
if(ch[0][i])
{
Q.push(ch[0][i]);
ins(0,ch[0][i]);
}
while(!Q.empty())
{
int r=Q.front();Q.pop();
for(int i=1;i<=26;i++)
{
int u=ch[r][i];
if(!u)
{
ch[r][i]=ch[fail[r]][i];
continue;
}
Q.push(u);
int p=fail[r];
while(p&&!ch[p][i]) p=fail[p];
fail[u]=ch[p][i];
ins(ch[p][i],u);
}
}
}
void work()
{
int p=0,H=1,t=0;
int n=strlen(s+1);
for(int i=1;i<=n;i++)
{
if(s[i]>='a'&&s[i]<='z')
{
p=ch[p][s[i]-'a'+1];
add(in[p],1);
}
else if(s[i]=='B')
{
add(in[p],-1);
p=fa[p];
}
else
{
t++;
while(q[H].y==t)
{
int x=id[q[H].x];
ANS[q[H].id]=ask(out[x])-ask(in[x]-1);
H++;
}
}
}
}
}AC;
int main()
{
scanf("%s",s+1);
AC.insert();AC.build();
int m;scanf("%d",&m);
for(int i=1;i<=m;i++)
{
read(q[i].x);
read(q[i].y);
q[i].id=i;
}
dfs(0);N=dfs_c;
sort(q+1,q+m+1,cmp);
AC.work();
for(int i=1;i<=m;i++)
printf("%d\n",ANS[i]);
return 0;
}