啊为了这道题花了接近半天的时间……主要还是因为自己效率太低……以及太弱……
思路:
m个询问,每个询问x y 问x在y中出现多少次
y–包含串 x–被包含串
求第x个打印的字符串在第y个打印的字符串中出现了多少次。
先建造ac自动机及fail指针,再以fail的反指针建造fail树。
x在y中出现多少次 =查x字符串的末尾指向y的fail反指针有多少=是此时在x的子树中有多少y串中的点=统计子树和
还有一些需要注意的细节,具体看代码:
/**************************************************************
Problem: 2434
User: DD_D
Language: C++
Result: Accepted
Time:668 ms
Memory:16584 kb
****************************************************************/
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int M=1e5+5,N=1e5+5;
char s[N];
int rt,ch[N][26],ptot,etot,m,len;
int to[N],head[N],nxt[N],in[N],out[N],idc,c[N],ans[M],ed[N],fa[N];
int fail[N];
struct type{
int x,y,id;
}a[M];
int cmp(type a,type b)
{
return a.y!=b.y?a.y<b.y:a.x<b.x;
}
void build()
{
int now=rt,cnt=0/**/;
for(int i=1;i<=len;i++){
if(s[i]=='P') ed[++cnt]=now;
else if(s[i]=='B') now=fa[now];
else if(ch[now][s[i]-'a']==-1)
ch[now][s[i]-'a']=++ptot,fa[ptot]=now,now=ptot;
else now=ch[now][s[i]-'a'];
}
}
void get_fail()
{
queue<int> q;
fail[rt]=0;
q.push(rt);
//!!!!!建fail的时候一定要记得特判第一层!!!
while(!q.empty()){
int now=q.front();q.pop();
for(int i=0;i<26;i++){
if(ch[now][i]!=-1) {
q.push(ch[now][i]);
fail[ch[now][i]]= now==0?0:ch[fail[now]][i];
}
else ch[now][i]= now==0?0:ch[fail[now]][i];
}
}
}
void adde(int u,int v)
{
to[++etot]=v;
nxt[etot]=head[u];
head[u]=etot;
}
void dfs(int u)
{
in[u]=++idc;
for(int i=head[u];i;i=nxt[i]) dfs(to[i]);
out[u]=idc;
}
void init()
{
ptot=0;
memset(ch,-1,sizeof(ch));
}
void add(int x,int d)
{
for(int i=x;i<=idc;i+=i&(-i))
c[i]+=d;
}
int query(int l,int r)
{
int a1=0,a2=0;
for(int i=l-1;i>=1;i-=i&(-i))
a1+=c[i];
for(int i=r;i>=1;i-=i&(-i))
a2+=c[i];
return a2-a1;
}
//solve的步骤:
//y完了后,要查x字符串的末尾指向它的fail反指针有多少,也就是此时在x的子树中
//有多少y串中的点,也就是统计子树和
//不用担心x的子树里有除y以外其他串的原因:y字符串不是从P开始而是从头开始
//所以现在没有因为B而被删的字符都属于y字符串
void solve()
{
int now=rt,cnt=0,k=1;
for(int i=1;i<=len;i++){
if(s[i]=='P'){
cnt++;
if(cnt==a[k].y){
for(;a[k].y==cnt;k++)
ans[a[k].id]=query(in[ed[a[k].x]],out[ed[a[k].x]]);
}
}
else if(s[i]=='B') add(in[now],-1),now=fa[now];
else now=ch[now][s[i]-'a'],add(in[now],1);
}
}
int main()
{
init();
scanf("%s",s+1);
len=strlen(s+1);
build();
get_fail();
for(int i=1;i<=ptot;i++)
adde(fail[i],i);
dfs(rt);
scanf("%d",&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&a[i].x,&a[i].y);
a[i].id=i;
}
sort(a+1,a+1+m,cmp);
solve();
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
return 0;
}