题解:在线建立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; }