AC自动机
Tags:字符串
作业部落
一、概述
(Aho-Corasic automaton),中文名(AC)自动机,是(Trie)图的一种,实现高效多串匹配单串的一种字符串算法
跟踪dalao的blog
(Trie)树上令一个点表示从根到它的串,那么一个点的fail
指向和它拥有最长后缀的串(所以可以指向(0))
二、题单
- [x] [luogu3808]【模板】AC自动机(简单版) https://www.luogu.org/problemnew/show/P3808
- [x] [luogu3796]【模板】AC自动机(加强版)https://www.luogu.org/problemnew/show/P3796
- [x] [CJOJ1435] 【模板题 USACO】AC自动机 https://oj.changjun.com.cn/problem/detail/pid/1435
- [x] [HDU2296]Ring https://vjudge.net/problem/HDU-2296#author=prayerhgq
- [x] [BZOJ1030][JSOI2007]文本生成器 https://www.luogu.org/problemnew/show/P4052
- [x] [BZOJ3172][TJOI2013]单词 https://www.luogu.org/problemnew/show/P3966
- [x] [Luogu2444][POI2000]病毒 https://www.luogu.org/problemnew/show/P2444
- [x] [BZOJ1009][HNOI2008]GT考试 https://www.luogu.org/problemnew/show/P3193
- [x] [BZOJ3530][SDOI2014]数数 https://www.luogu.org/problemnew/show/P3311
- [x] [Luogu3121][USACO15FEB]审查Censoring https://www.luogu.org/problemnew/show/P3121
- [x] [BZOJ1212][HNOI2004]L语言 https://www.luogu.org/problemnew/show/P2292
- [x] [Luogu3041][USACO12JAN]视频游戏的连击Video Game Combos https://www.luogu.org/problemnew/show/P3041
- [ ] [BZOJ2434]阿狸的打字机 https://www.luogu.org/problemnew/show/P2414
- [ ] [BZOJ2754]喵星球上的点名 https://www.luogu.org/problemnew/show/P2336
- [ ] [BZOJ1444][Jsoi2009]有趣的游戏 https://www.lydsy.com/JudgeOnline/problem.php?id=1444
- [ ] [BeiJing2011]禁忌 https://www.luogu.org/problemnew/show/P4569
- [ ] [Ahoi2005]VIRUS 病毒检测 https://www.luogu.org/problemnew/show/P2536
- [ ] [Cqoi2014]通配符匹配 https://www.luogu.org/problemnew/show/P3167
- [ ] [HNOI2006]最短母串 https://www.luogu.org/problemnew/show/P2322
- [ ] [HEOI2012]旅行问题 https://www.luogu.org/problemnew/show/P4600
三、做题经验
1
用来多串匹配单串或多串,效率高于(KMP)(可以代替),但是字符集很大时候需要大空间或用时间换空间(开(set))
2
套路:(dp[i][j])表示到第(i)号节点(长串匹配到(i)),匹配长度为(j)(短串匹配到(j))的方案数啥的
四、Tip
!
(Fail)是一棵树,但是(AC)自动机是(Trie)图,可以存在环(病毒)
!
构造数据的时候,可以检查自己写的(AC)自动机是否可以从第一位开始匹配
五、模板
洛谷3808模板1
首先建出(Trie)树((Build)),然后通过(BFS)算出(Fail),再进行匹配
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN=1000100;
struct Node{int ch[26],fail,end;}t[MAXN];
char s[MAXN];
int N,node;
queue<int> Q;
void Build()
{
int len=strlen(s),x=0;
for(int i=0;i<len;i++)
{
if(!t[x].ch[s[i]-'a']) t[x].ch[s[i]-'a']=++node;
x=t[x].ch[s[i]-'a'];
}
t[x].end++;
}
void Get_Fail()
{
for(int i=0;i<26;i++) if(t[0].ch[i]) Q.push(t[0].ch[i]);
while(!Q.empty())
{
int x=Q.front();Q.pop();
for(int i=0;i<26;i++)
if(t[x].ch[i])
{
t[t[x].ch[i]].fail=t[t[x].fail].ch[i];
Q.push(t[x].ch[i]);
}
else t[x].ch[i]=t[t[x].fail].ch[i];
}
}
int AC()
{
int len=strlen(s),x=0,ans=0;
for(int i=0;i<len;i++)
{
x=t[x].ch[s[i]-'a'];
for(int p=x;p&&~t[p].end;p=t[p].fail)
ans+=t[p].end,t[p].end=-1;
}
return ans;
}
int main()
{
cin>>N;while(N--){scanf("%s",s);Build();}
Get_Fail();scanf("%s",s);
printf("%d
",AC());return 0;
}
六、一句话题解
[luogu3808]【模板】AC自动机(简单版)
把模式串的AC自动机建好后用文本串匹配,匹配完成就删去此串及其后缀
[luogu3796]【模板】AC自动机(加强版)
[CJOJ1435] 【模板题 USACO】AC自动机
[BZOJ3172][TJOI2013]单词
统计每个模式串出现次数,匹配时打个标记,然后用(fail)树DFS完成统计数量
[HDU2296]Ring
(dp[i][j])表示母串匹配到第(i)位,匹配到AC自动机上第(j)个节点的最大权值,同时记录(string qq[i][j])表示选择的方案
[BZOJ1030][JSOI2007]文本生成器
(dp[i][j])表示生成文本长度为(i),匹配到AC自动机上第(j)个节点的没有出现认识的单词的方案数,最后用总方案减去所有不合法方案即为答案
[Luogu2444][POI2000]病毒
Hard
如果AC自动机上出现了没有(end)标记的环那么就存在无限长的串使得不存在任何模式串
[BZOJ1009][HNOI2008]GT考试
Hard
(dp[i][j])表示长串枚举到(i)短串匹配到(j)的方案数,由于短串很短,所以另(G[i][j])表示短串从上次匹配的(s[i])下一位将要匹配(k=1...9)从而匹配/失配到了(s[j])的方案数,使用矩阵乘法,(F[0][0]=1,F*G)表示枚举下一位数字是几来更新方案数
[BZOJ3530][SDOI2014]数数
Hard
数位DP,(dp[i][j][0/1/2])表示数字有(i)位,AC自动机上匹配到第(j)个节点,比(N)小/等/大的方案数,最后统计位数比(N)小的所有答案以及位数等于(N)的(0/1)
[Luogu3121][USACO15FEB]审查Censoring
Hard
建好AC自动机后跑匹配,记录匹配母串中每个字符出现的位置,如果遇到(end)节点那么回到该词前一个字符的位置,继续向下匹配
[BZOJ1212][HNOI2004]L语言
Hard
AC自动机:可以识别的是若干个区间,从起点起(BFS),能够被搜到的最右端节点即为答案
Trie树DP:字符串反转后建(Trie树),(dp[i])表示(s_{1..p})能否被识别,当(s_{i..j})是(Trie)树上的一个单词的时候(dp[i]|=dp[j])
[Luogu3041][USACO12JAN]视频游戏的连击Video Game Combos
(dp[i][j])表示母串长度为(i),匹配到AC自动机上第(j)个节点的最大分数
- [ ] [BZOJ2434]阿狸的打字机 https://www.luogu.org/problemnew/show/P2414
- [ ] [BZOJ2754]喵星球上的点名 https://www.luogu.org/problemnew/show/P2336
- [ ] [BZOJ1444][Jsoi2009]有趣的游戏 https://www.lydsy.com/JudgeOnline/problem.php?id=1444
- [ ] [BeiJing2011]禁忌 https://www.luogu.org/problemnew/show/P4569
- [ ] [Ahoi2005]VIRUS 病毒检测 https://www.luogu.org/problemnew/show/P2536
- [ ] [Cqoi2014]通配符匹配 https://www.luogu.org/problemnew/show/P3167
- [ ] [HNOI2006]最短母串 https://www.luogu.org/problemnew/show/P2322
- [ ] [HEOI2012]旅行问题 https://www.luogu.org/problemnew/show/P4600