题解:在线建立AC自动机,建好Fail树,a是b的子串也就是b到root的节点能沿Fail树走到a
离线所有询问,DFS一遍的时候顺便处理询问
或按b排序在AC自动机上走也可以
用树状数组维护,查询区间和即可
一开始LCA打错了竟然得了70害得我找不出错
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=200009;
int T;
int n;
int p[maxn];
int cntedge;
int head[maxn];
int to[maxn<<1],nex[maxn<<1];
void Addedge(int x,int y){
// printf("%d -> %d\n",x,y);
nex[++cntedge]=head[x];
to[cntedge]=y;
head[x]=cntedge;
}
int dfsclock;
int father[maxn],idx[maxn],siz[maxn];
void Dfs(int now,int fa){
father[now]=fa;
idx[now]=++dfsclock;
siz[now]=1;
for(int i=head[now];i;i=nex[i]){
if(to[i]==fa)continue;
Dfs(to[i],now);
siz[now]+=siz[to[i]];
}
}
int nn;
char s[maxn];
int ch[maxn][30];
int ff[maxn];
int dep[maxn];
int f[maxn][20];
queue<int>q;
int fai[maxn];
void GetFail(){
fai[1]=1;
for(int c=0;c<26;++c){
int v=ch[1][c];
if(v){
// cout<<"eatingshit"<<‘ ‘<<c<<endl;
fai[v]=1;
Addedge(1,v);
q.push(v);
}
}
while(!q.empty()){
int u=q.front();q.pop();
for(int c=0;c<26;++c){
int v=ch[u][c];
if(!v)continue;
int j=fai[u];
while((j!=1)&&(!ch[j][c]))j=fai[j];
if(ch[j][c]){
fai[v]=ch[j][c];
}else{
fai[v]=1;
}
Addedge(fai[v],v);
q.push(v);
}
}
}
void check(int x,int dep){
printf("%d %d\n",x,dep);
for(int c=0;c<26;++c){
if(ch[x][c])check(ch[x][c],dep+1);
}
}
void LCAinit(){
for(int i=1;i<=nn;++i)f[i][0]=ff[i];
for(int j=1;j<=16;++j){
for(int i=1;i<=nn;++i){
f[i][j]=f[f[i][j-1]][j-1];
}
}
}
int Getlca(int u,int v){
if(dep[u]<dep[v])swap(u,v);
for(int j=16;j>=0;--j){
if(dep[f[u][j]]>=dep[v]){
u=f[u][j];
}
}
if(u==v)return u;
for(int j=16;j>=0;--j){
if(f[u][j]!=f[v][j]){
u=f[u][j];v=f[v][j];
}
}
return f[u][0];
}
int c[maxn];
inline int lowbit(int x){
return x&(-x);
}
void Addpoint(int x,int val){
while(x<=nn){
c[x]+=val;
x+=lowbit(x);
}
}
int Querypre(int x){
int ret=0;
while(x){
ret+=c[x];
x-=lowbit(x);
}
return ret;
}
int ans[maxn];
struct Querys{
int qx,qy,t;
}que[maxn];
int cmp(const Querys &rhs1,const Querys &rhs2){
return rhs1.qy<rhs2.qy;
}
void Minit(){
n=cntedge=nn=dfsclock=0;
memset(father,0,sizeof(father));
memset(head,0,sizeof(head));
memset(ch,0,sizeof(ch));
memset(ff,0,sizeof(ff));
memset(dep,0,sizeof(dep));
memset(f,0,sizeof(f));
memset(c,0,sizeof(c));
while(!q.empty())q.pop();
}
int main(){
// freopen("print.in","r",stdin);
// freopen("print.out","w",stdout);
Minit();
scanf("%s",s);
int len=strlen(s);
// cout<<len<<endl;
nn=1;
int nowx=1;
dep[nowx]=1;
for(int i=0;i<len;++i){
if(s[i]==‘P‘){
p[++n]=nowx;
}else if(s[i]==‘B‘){
nowx=ff[nowx];
}else{
int c=s[i]-‘a‘;
if(ch[nowx][c]){
nowx=ch[nowx][c];
}else{
ch[nowx][c]=++nn;
ff[ch[nowx][c]]=nowx;
dep[ch[nowx][c]]=dep[nowx]+1;
nowx=ch[nowx][c];
}
}
}
// check(1,1);
LCAinit();
GetFail();
Dfs(1,0);
scanf("%d",&T);
for(int i=1;i<=T;++i){
scanf("%d%d",&que[i].qx,&que[i].qy);
que[i].t=i;
}
sort(que+1,que+1+T,cmp);
// cout<<"eatingshit"<<endl;
for(int i=1;i<=T;++i){
que[i].qx=p[que[i].qx];
que[i].qy=p[que[i].qy];
// printf("%d %d\n",que[i].qx,que[i].qy);
}
// cout<<"eeee"<<endl;
int lastp=1;
Addpoint(idx[lastp],1);
for(int i=1;i<=T;++i){
// cout<<i<<endl;
int y=que[i].qy;
int lca=Getlca(lastp,y);
// printf("%d %d %d\n",lca,dep[lastp]-dep[lca],dep[y]-dep[lca]);
while(lastp!=lca){
Addpoint(idx[lastp],-1);
lastp=ff[lastp];
}
// cout<<"emmmmm"<<endl;
lastp=y;
while(y!=lca){
// cout<<y<<‘ ‘<<idx[y]<<endl;
Addpoint(idx[y],1);
y=ff[y];
}
ans[que[i].t]=-Querypre(idx[que[i].qx]-1)+Querypre(idx[que[i].qx]+siz[que[i].qx]-1);
}
for(int i=1;i<=T;++i)printf("%d\n",ans[i]);
return 0;
}