[bzoj2434]阿狸的打字机
按要求模拟建AC自动机,我们看可以发现答案就是fail树上的子树中出现的end节点个数。离线然后在trie上dfs,遇到对应节点就更新答案
- 代码
#include<bits/stdc++.h>
using namespace std;
const int N=4e5+5;
const int SZ=26;
struct trie{
int ch[SZ],fail;
int fa;
}t[N];
int fail[N];
int root=0,cnt=0;
int pos[N],n,m;
char str[N];
inline void ins(char ch[]){
int len=strlen(ch+1);
int cur=root;
for(int i=1;i<=len;++i){
if(ch[i]=='P')pos[++n]=cur;
else if(ch[i]=='B')cur=t[cur].fa;
else {
int c=ch[i]-'a';
if(t[cur].ch[c])cur=t[cur].ch[c];
else {
t[++cnt].fa=cur;cur=t[cur].ch[c]=cnt;
}
}
}
}
int hed[N],nxt[N],to[N];
int tot;
inline void adde(int u,int v){
tot++;to[tot]=v,nxt[tot]=hed[u];hed[u]=tot;
}
queue<int>q;
inline void build(){
for(int i=0;i<SZ;i++)if(t[0].ch[i]){
fail[t[0].ch[i]]=0;
q.push(t[0].ch[i]);
adde(0,t[0].ch[i]);
}
while(!q.empty()){
int u=q.front();q.pop();
for(int c=0;c<SZ;c++)if(t[u].ch[c]){
int x=fail[u];
while(x&&!t[x].ch[c])x=fail[x];
if(t[x].ch[c])x=t[x].ch[c];
fail[t[u].ch[c]]=x;
adde(x,t[u].ch[c]);
q.push(t[u].ch[c]);
}
}
}
int dfn[N],num,sz[N];
inline void dfs(int x){
dfn[x]=++num,sz[x]=1;
for(int i=hed[x];i;i=nxt[i]){
int v=to[i];
dfs(v);
sz[x]+=sz[v];
}
}
int triedfn[N],cont;
struct question{
int L,R,id;
bool operator < (const question b)const{return triedfn[pos[R]]<triedfn[pos[b.R]];}
}Q[N];
#define lowbit(x) ((x)&(-x))
int Sum[N];
inline void add(int pos,int add){
for(;pos<=num;pos+=lowbit(pos))Sum[pos]+=add;
}
inline int query(int pos){
int ans=0;
for(;pos;pos-=lowbit(pos))ans+=Sum[pos];
return ans;
}
inline int askson(int pos){
int l=dfn[pos]-1;
int r=dfn[pos]+sz[pos]-1;
return query(r)-query(l);
}
int ans[N];
int L[N],R[N];
int II=1;
inline void dfstrie(int x){
add(dfn[x],1);
while(II<=m&&triedfn[pos[Q[II].R]]==triedfn[x]){
ans[Q[II].id]=askson(pos[Q[II].L]);
++II;
}
for(int i=0;i<SZ;i++)if(t[x].ch[i]){
dfstrie(t[x].ch[i]);
}
add(dfn[x],-1);
}
inline void dfsprep(int x){
triedfn[x]=++cont;
for(int i=0;i<SZ;i++)if(t[x].ch[i]){
dfsprep(t[x].ch[i]);
}
}
int main()
{
scanf("%s",str+1);
ins(str);
build();
dfs(root);
dfsprep(root);
scanf("%d",&m);
for(int i=1;i<=m;++i){
Q[i].id=i;scanf("%d%d",&Q[i].L,&Q[i].R);
}
sort(Q+1,Q+m+1);
dfstrie(0);
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
}