【bzoj2434】阿狸的打字机

  • AC自动机重修系列第一题

今天吕老板讲了一发字符串,然后。。。我发现我好像学了假的AC自动机?

于是今晚恶补一发,此题便是AC自动机重修系列第一题

原先写这题的时候还是没有搞懂fail树这种神奇的东西,于是我去百度了一下,有一篇博文写得很好传送门

查询x在y中的出现次数,我们可以离线搞

对于每个询问,从y向x连边,那么我们在跑AC自动机时,每得到一个串就可以计算该串对应的x的答案

关于删除操作,只需要在建AC自动机时返回父节点即可,注意下面代码中的fail和f不可混淆

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include<bits/stdc++.h>
#define FILE "read"
#define MAXN 200010
using namespace std;
struct node{int y,next;}e[MAXN],qe[MAXN];
int n,m,cnt,len,dfs_clock,ans[MAXN],pos[MAXN],fail[MAXN],f[MAXN],q[MAXN],Link[MAXN],qLink[MAXN],L[MAXN],R[MAXN],c[MAXN],tr[MAXN][26];
char ch[MAXN];
inline int read(){
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
void insert(int x,int y){e[++len].next=Link[x];Link[x]=len;e[len].y=y;}
void add(int x,int v){while(x<=dfs_clock)c[x]+=v,x+=(x&-x);}
int get(int x){int temp(0);while(x)temp+=c[x],x-=(x&-x);return temp;}
void extend(){
int now=0,id=0;
for(int i=1;i<=n;++i){
if(ch[i]=='P') pos[++id]=now;
else if(ch[i]=='B') now=f[now];
else{
if(!tr[now][ch[i]-'a']) tr[now][ch[i]-'a']=++cnt,f[cnt]=now;
now=tr[now][ch[i]-'a'];
}
}
}
void build(){
int head=0,tail=0;
for(int i=0;i<26;++i) if(tr[0][i]) q[++tail]=tr[0][i];
while(++head<=tail){
int x=q[head];
for(int i=0;i<26;++i){
if(!tr[x][i]) tr[x][i]=tr[fail[x]][i];
else fail[tr[x][i]]=tr[fail[x]][i],q[++tail]=tr[x][i];
}
}
for(int i=1;i<=cnt;++i) insert(fail[i],i);
}
void init(){
scanf("%s",ch+1); n=strlen(ch+1);
extend(); build(); m=read();
for(int i=1;i<=m;++i){
int x=read(),y=read();
qe[i].next=qLink[y];qLink[y]=i;qe[i].y=x;
}
}
void dfs(int x){
L[x]=++dfs_clock;
for(int i=Link[x];i;i=e[i].next)
dfs(e[i].y);
R[x]=++dfs_clock;
}
void solve(){
dfs(0); int now=0,id=0;
for(int i=1;i<=n;++i){
if(ch[i]=='P'){
for(int j=qLink[++id];j;j=qe[j].next){
int x=pos[qe[j].y];
ans[j]=get(R[x])-get(L[x]-1);
}
}
else if(ch[i]=='B') add(L[now],-1),now=f[now];
else now=tr[now][ch[i]-'a'],add(L[now],1);
}
for(int i=1;i<=m;++i) printf("%d\n",ans[i]);
}
int main(){
freopen(FILE".in","r",stdin);
freopen(FILE".out","w",stdout);
init();
solve();
return 0;
}
文章目录
,