题面:
题解:
离线 + fail树
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<vector>
#define ll long long
using namespace std;
const int maxn=101000;
int t[maxn][26];
int fail[maxn],fa[maxn],id[maxn];
int st[maxn],ed[maxn];
int tot=0,cnt=0,num=0;
char str[maxn];
int head[maxn],ver[maxn],nt[maxn];
int pt=0;
int ans[maxn];
int sum[maxn];
//插入一个字符
int _insert(int p,int k)
{
if(t[p][k]) return t[p][k];
t[p][k]=++cnt;fa[t[p][k]]=p;
return t[p][k];
}
//删除一个字符
int del(int p)
{
return fa[p];
}
//标记为结尾
void is_end(int p)
{
id[++num]=p;
}
//建立AC自动机
void getfail(void)
{
queue<int>q;
for(int i=0;i<26;i++)
{
if(t[0][i])
{
fail[t[0][i]]=0;
q.push(t[0][i]);
}
}
while(q.size())
{
int now=q.front();
q.pop();
for(int i=0;i<26;i++)
{
int p=t[now][i];
if(p)
{
fail[p]=t[fail[now]][i];
q.push(p);
}
else
t[now][i]=t[fail[now]][i];
}
}
}
//建立fail树
void add(int x,int y)
{
ver[++pt]=y,nt[pt]=head[x],head[x]=pt;
}
void build(void)
{
for(int i=1;i<=cnt;i++)
add(fail[i],i);
}
//遍历dfs序
void dfs_fail_tree(int x)
{
st[x]=++tot;
for(int i=head[x];i;i=nt[i])
dfs_fail_tree(ver[i]);
ed[x]=tot;
}
//询问离线
struct node
{
int x,y;
int id;
node(int a=0,int b=0,int c=0)
{
x=a,y=b,id=c;
}
bool operator <(const node &b)const
{
return y<b.y;
}
}cm[maxn];
void ad(int x,int val)
{
for(;x<maxn;x+=(x&(-x)))
sum[x]+=val;
}
int ask(int x)
{
int ans=0;
for(;x;x-=(x&(-x)))
ans+=sum[x];
return ans;
}
void get_ans(int len,int m)
{
int cmt=1;
int numt=0;
int np=0;
for(int i=1;i<=len;i++)
{
if(str[i]=='P')
{
numt++;
while(cmt<m&&cm[cmt].y<numt) cmt++;
while(cmt<=m&&cm[cmt].y==numt)
{
int x=cm[cmt].x;
//查询x的结尾节点的子树
ans[cm[cmt].id]=ask(ed[id[x]])-ask(st[id[x]]-1);
cmt++;
}
}
else if(str[i]=='B')
{
ad(st[np],-1);
np=fa[np];
}
else
{
np=t[np][str[i]-'a'];
ad(st[np],1);
}
}
}
int main(void)
{
scanf("%s",str+1);
int len=strlen(str+1);
int np=0;
for(int i=1;i<=len;i++)
{
if(str[i]=='B') np=del(np);
else if(str[i]=='P') is_end(np);
else np=_insert(np,str[i]-'a');
}
getfail();
build();
int m,x,y;
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
cm[i]=node(x,y,i);
}
sort(cm+1,cm+m+1);
dfs_fail_tree(0);
get_ans(len,m);
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
return 0;
}