AC自动机学习笔记
学了AC自动机就能自动AC
才怪
可以先看yyb老爷的博文,精妙无双
不定期更?
Upd:2019.6.6
001
前置知识:字典树(Trie树),KMP
关于AC自动机,日报上愤怒地指责了当前许多dalao感性地将其表述为Trie+KMP的行为
我:虽然我是菜鸡,但。。。确实是Trie上KMP啊
和KMP一样,AC自动机的失配(fail)指针也是继续匹配用的,而AC自动机主要就是构建fail指针
Code
void getfail()
{
queue<int>Q;
for(int i=1;i<=26;i++)
{
if(Trie[0].vis[i])
{
Trie[Trie[0].vis[i]].fail=0;
Q.push(Trie[0].vis[i]);
}
}
while(!Q.empty())
{
int T=Q.front();
Q.pop();
for(int i=1;i<=26;i++)
{
if(Trie[T].vis[i])
{
Trie[Trie[T].vis[i]].fail=Trie[Trie[T].fail].vis[i];
Q.push(Trie[T].vis[i]);
}
else
{
Trie[T].vis[i]=Trie[Trie[T].fail].vis[i];
}
}
}
}
再贴一个Trie?
开个玩笑
Code
struct node
{
int vis[27],fail,end;
}Trie[1000010];
void build()
{
int len=strlen(C+1);
int now=0;
for(int i=1;i<=len;i++)
{
if(!Trie[now].vis[C[i]-'a'+1])
{
Trie[now].vis[C[i]-'a'+1]=++cnt;
}
now=Trie[now].vis[C[i]-'a'+1];
}
Trie[now].end++;
}
002
板题(减'a'后没加1调了我好久QwQ):
P3808 【模板】AC自动机(简单版)
Code
#include<bits/stdc++.h>
using namespace std;
int n,cnt;
char C[1000010];
struct node
{
int vis[27],fail,end;
}Trie[1000010];
void build()
{
int len=strlen(C+1);
int now=0;
for(int i=1;i<=len;i++)
{
if(!Trie[now].vis[C[i]-'a'+1])
{
Trie[now].vis[C[i]-'a'+1]=++cnt;
}
now=Trie[now].vis[C[i]-'a'+1];
}
Trie[now].end++;
}
void getfail()
{
queue<int>Q;
for(int i=1;i<=26;i++)
{
if(Trie[0].vis[i])
{
Trie[Trie[0].vis[i]].fail=0;
Q.push(Trie[0].vis[i]);
}
}
while(!Q.empty())
{
int T=Q.front();
Q.pop();
for(int i=1;i<=26;i++)
{
if(Trie[T].vis[i])
{
Trie[Trie[T].vis[i]].fail=Trie[Trie[T].fail].vis[i];
Q.push(Trie[T].vis[i]);
}
else
{
Trie[T].vis[i]=Trie[Trie[T].fail].vis[i];
}
}
}
}
int ACJ()
{
int len=strlen(C+1);
int now=0,ans=0;
for(int i=1;i<=len;i++)
{
now=Trie[now].vis[C[i]-'a'+1];
for(int j=now;j&&Trie[j].end!=-1;j=Trie[j].fail)
{
ans+=Trie[j].end;
Trie[j].end=-1;
}
}
return ans;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s",C+1);
build();
}
Trie[0].fail=0;
getfail();
scanf("%s",C+1);
cout<<ACJ();
}