【模板】AC自动机
忘了博客地址了。
后续可能上升为总结。
代码比较复杂,细节很多,建议背下来。
【模板】AC自动机(简单版)
由势能分析可知,Query 部分时间复杂度是
O
(
2
∗
l
e
n
T
)
O(2*lenT)
O(2∗lenT)
统计
f
a
i
l
fail
fail 答案部分是长度和,因为只统计是否出现。
#include<bits/stdc++.h>
using namespace std;
const int MAXC=26;
const int N=1e6+5;
struct node{
int cnt,fail,nxt[MAXC];
}t[N];
int root,tot=1,res=0,T,n;
queue<int> Q;
char article[N],word[N];
void insert(char *s) {
int len=strlen(s),r=1;
for(int i=0;i<len;i++) {
if(!t[r].nxt[s[i]-'a']) t[r].nxt[s[i]-'a']=++tot;
r=t[r].nxt[s[i]-'a'];
}
t[r].cnt++;
}
void build() {//AcMachine
t[1].fail=1;
Q.push(1);
while(Q.size()) {//order in depth
int r=Q.front();Q.pop();
for(int i=0;i<MAXC;i++) {
int ch=t[r].nxt[i],p;
if(ch) {
Q.push(ch);
for(p=t[r].fail;p!=1&&t[p].nxt[i]==0;p=t[p].fail);
int tmp=t[p].nxt[i];
if(tmp&&tmp!=ch) t[ch].fail=tmp;
else t[ch].fail=1;
}
}
}
}
void Query(char *s) {
int r=1,len=strlen(s);
for(int i=0;i<len;i++) {
int p;
for(p=r;p!=1&&t[p].nxt[s[i]-'a']==0;p=t[p].fail);
r=t[p].nxt[s[i]-'a'];
if(r==0) r=1;
for(int temp=r;temp!=1;temp=t[temp].fail) {
if(t[temp].cnt==-1) break;
res+=t[temp].cnt;
t[temp].cnt=-1;
}
}
}
int main() {
// freopen("1.in","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%s",word);
insert(word);
}
// printf("yes");
scanf("%s",article);
build();
// for(int i=1;i<=tot;i++) printf("fail[%d]=%d\n",i,t[i].fail);
Query(article);
printf("%d",res);
}
【模板】AC自动机(二次加强版)
区别只在于加了一个
t
o
p
o
topo
topo 排序。
#include<bits/stdc++.h>
using namespace std;
const int MAXC=26;
const int N=2e6+5;
struct node{
int cnt,end,fail,nxt[MAXC];
}t[N];
int root,tot=1,res=0,T,n,ans[N];
int c[N];
int in[N];
queue<int> Q;
char article[N],word[N];
int insert(char *s) {
int len=strlen(s),r=1;
for(int i=0;i<len;i++) {
if(!t[r].nxt[s[i]-'a']) t[r].nxt[s[i]-'a']=++tot;
r=t[r].nxt[s[i]-'a'];
}
t[r].end=1;
return r;
}
void build() {//AcMachine
t[1].fail=1;
Q.push(1);
while(Q.size()) {//order in depth
int r=Q.front();Q.pop();
for(int i=0;i<MAXC;i++) {
int ch=t[r].nxt[i],p;
if(ch) {
Q.push(ch);
for(p=t[r].fail;p!=1&&t[p].nxt[i]==0;p=t[p].fail);
int tmp=t[p].nxt[i];
if(tmp&&tmp!=ch) t[ch].fail=tmp;
else t[ch].fail=1;
}
}
}
}
void Query(char *s) {
int r=1,len=strlen(s);
for(int i=0;i<len;i++) {
int p;
for(p=r;p!=1&&t[p].nxt[s[i]-'a']==0;p=t[p].fail);
r=t[p].nxt[s[i]-'a'];
if(r==0) r=1;
t[r].cnt++;
// for(int temp=r;temp!=1;temp=t[temp].fail) {
// if(t[temp].cnt==-1) break;
// res+=t[temp].cnt;
// t[temp].cnt++;
// }
}
}
int main() {
// freopen("1.in","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%s",word);
ans[i]=insert(word);
}
// printf("yes");
scanf("%s",article);
build();
// for(int i=1;i<=tot;i++) printf("fail[%d]=%d\n",i,t[i].fail);
Query(article);
while(Q.size()) Q.pop();
for(int i=1;i<=tot;i++) in[t[i].fail]++;
for(int i=1;i<=tot;i++) if(!in[i]) Q.push(i);
while(Q.size()) {
int x=Q.front();Q.pop();
t[t[x].fail].cnt+=t[x].cnt;
if(--in[t[x].fail]==0) Q.push(t[x].fail);
}
for(int i=1;i<=n;i++) printf("%d\n",t[ans[i]].cnt);
}

浙公网安备 33010602011771号