前言

一言不合就开坑,说的就是我~
之前觉得这东西挺难,然后某天早上花了一个半小时就学会了……

P.S:如果你诚心诚意的想学会AC自动机,一定要先去看懂KMP和Trie。
而且一定要好好理解KMP的next~

1.What is AC自动机?

就是通过不懈的努力,最终发明了自动帮你A题的算法
如果需要相关信息可以去百度百科一些知识,比如什么是自动机,什么是AC……

我在这里只说一下自己的看法:

从应用角度来说:这个东西主要用于解决多个串的匹配问题,最经典的例题就是:
找给定的n个串在给定的某文本中(出现了多少次)/(各出现多少次 )

从算法角度来说:如同绝大多数人说的那样,这其实就是Trie树+KMP而已。

那么看这篇文章请随时记住几个关键词:
前缀、失配

2.How to do it?

我们还是搬出经典的例题:

给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过。

有没有什么想法?
容易想到的暴力是跑n遍KMP,每个串配一次,或者是建个trie树,也是跑n遍。
不过这个数据范围一点也不友好:

∑ len(模式串)<=106,length(文本串)<=106

这个时候AC自动机就发挥作用了,它的时间复杂度为 O(能过)
其实是我不会分析复杂度不信你看以前的也没有
那么构造一个AC自动机需要以下三步:

1、造一个Trie树

啊,对,就是造个Trie树,没有什么特殊的地方,老老实实insert就完了。

struct Node{int son[27],num;}node[N<<2];ivoid insert(char *c,int rank)
{int len=strlen(c),now=0;for(rint i=0;i<len;i++){int d=c[i]-'a';if(!node[now].son[d]){node[now].son[d]=++cnt;}now=node[now].son[d];}node[now].num++;
}
2、构造失配指针

AC自动机的重点难点就是在这个地方:怎样把KMP的失配指针的思想给用上?

①举例分析

我们来考虑一下上面那个例题在做的时候需要怎样的优化:

假设给定的模式串是:SHE HE HER SAY SHR
我们构建出来的Trie树该是这个样子
(图片来源:http://www.cnblogs.com/cjyyb/p/7196308.html) (另作了修改)

①假设我们的文本串是 SHA
那么按照常规方法,我们会检索到S,走S-H,失配,检索到H,走H-A。

现在失配指针就要派上用场了!我们希望S-H之后直接跳到旁边的H-A去,以此来节约时间。我们敢这么干的原因是什么?原因之一是因为两边都有H。

那么失配指针构造的显而易见的原则之一:出现相同字母

②假设我们的文本串是SHER
常规就不说了

这里的失配指针自然是从SHE的E指向HER的E。那么问题来了,我们能不能从HER的E跳到SHE的E呢?显然不行。

原因很简单,HER的前缀不一定有S,可能不符合匹配要求
(为什么说不一定,因为AC自动机进行的是多次匹配,是可能存在之前出现S的情况的);

因而我们加失配指针的原则还有一个:从深度小的往深度大的加

②代码实现

那么我们分析倒是分析了,实际构造又该怎样呢?我们结合代码,分段来看一看:

ivoid build()
{queue<int>q1;for(rint i=0;i<26;i++){if(node[0].son[i]){q1.push(node[0].son[i]); }}

在这里我们从根节点0开始,把它的所有子节点加入队列中。

 while(!q1.empty()){int now=q1.front();q1.pop();for(rint i=0;i<26;i++){if(node[now].son[i]){fail[node[now].son[i]]=node[fail[now]].son[i];q1.push(node[now].son[i]);}

此处正在对每一个点的儿子进行检索,如果有这个儿子,那么把他的失配指针指向他父亲的失配指针指向的点的对应儿子。

emm也许有些不好理解,我们分类讨论:
那么情况一:父亲失配指针指向的点没有这个儿子,也就是继续失配。由于空节点的编号和根节点编号相同,相当于是指向了根节点。
情况二:xxxx的点有这个儿子,那么我们可以通过失配指针跳过去,再度向下寻找可以继续匹配的节点,没有就继续跳……一直到匹配成功或者回到根节点。

(其实这个地方大家可以想一想前向星的存边方法,跟这个失配指针不断跳是很类似的~)

else node[now].son[i]=node[fail[now]].son[i];

啥啥啥?为啥你把儿子共用了???
其实这地方的朴素写法是这样的:

else fail[node[now].son[i]=node[fail[now]].son[i];

但是本身你这个儿子就是空的,如果我们在运行的时候通过失配指针跳到这里,会发现完全没法匹配(空节点哪里来的儿子),于是就继续往后跳。
这是白白浪费了时间。因此我们就直接共用子节点, 只不过是从失配-跳一下fail-发现为空-继续跳fail-匹配成功,变成了直接匹配成功~

3、运行AC自动机

好了,树也有了,指针也好了,我们直接放上去跑就完事,不多说了:

//这是统计一共出现了多少个模式串
ivoid check(char *c)
{int len=strlen(c),now=ans=0;for(rint i=0;i<len;i++){now=node[now].son[c[i]-'a'];for(rint j=now;j&&node[j].num;j=fail[j]){ans+=node[j].num;node[j].num=0;}}
}

3、What can be solved?

AC自动机的运用范围主要是字符串相关,尤其是多串匹配的时候非常优秀,只不过面对某些毒瘤的要求或许需要改变统计的方法,或者是失配指针的构造法。
(其实最难的是看出这是AC自动机 )

最后推荐一道AC自动机的好题,可以大程度加深对AC自动机的理解:
P2444 [POI2000]病毒 -

【谈谈知识点】AC自动机相关推荐

  1. 提高篇 第二部分 字符串算法 第4章 AC自动机

    https://blog.csdn.net/wangyh1008/article/details/81428056 [模板]AC自动机(加强版) 洛谷3796 AC自动机_A_loud_name-CS ...

  2. 【BZOJ2553】禁忌,AC自动机+期望DP+矩乘

    传送门 先考虑选最多禁忌串的问题 感受一下,如果禁忌串之间没有包含关系,一定是可以从前往后贪心搞的,直接建AC自动机跑匹配,找到一个禁忌串的末尾就回到根上,并把禁忌串数量+1 (所以起初我想的是把包含 ...

  3. 2017 Multi-University Training Contest - Team 8:Fleet of the Eternal Throne(AC自动机)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6138 题目意思:题目给出n个字符串后,会有m个询问,每个询问会输入两个数,记为x,y吧. 然后要求的是 ...

  4. AC自动机从入门到last优化

    AC自动机是KMP算法和Trie(字典树)的巧妙结合这篇文章主要讲针对几个例题给出解答模版(主要是知识点自己讲不清楚). 至于针对的知识点,给上几个我认为说的比较好的传送门,读者可以自行选择阅读.(我 ...

  5. Aho-Corasick 多模式匹配算法(AC自动机) 的算法详解及具体实现

    多模式匹配 多模式匹配就是有多个模式串P1,P2,P3-,Pm,求出所有这些模式串在连续文本T1-.n中的所有可能出现的位置. 例如:求出模式集合{"nihao","ha ...

  6. 【BZOJ2434】[NOI2011]阿狸的打字机 AC自动机+DFS序+树状数组

    [BZOJ2434][NOI2011]阿狸的打字机 Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P ...

  7. AC自动机算法及模板

    AC自动机算法及模板 2016-05-08 18:58 226人阅读 评论(0) 收藏 举报  分类: AC自动机(1)  版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 关于 ...

  8. Keywords Search AC自动机QAQ

    AC自动机,一直以来都以为是一个非常高大上的算法,其实它还真的挺高大上的. 首先来说,ac自动机的思想与kmp类似,需要自己模拟来理解. 给两个博客: http://www.cppblog.com/m ...

  9. 字符串匹配算法 -- AC自动机 基于Trie树的高效的敏感词过滤算法

    文章目录 1. 算法背景 2. AC自动机实现原理 2.1 构建失败指针 2.2 依赖失败指针过滤敏感词 3. 复杂度及完整代码 1. 算法背景 之前介绍过单模式串匹配的高效算法:BM和KMP 以及 ...

最新文章

  1. 使用ZeroClipboard解决跨浏览器复制到剪贴板的问题
  2. hdu 5157(manacher+前缀和+树状数组)
  3. FPGA在其他领域的应用(二)
  4. Unity Hub安装Android Build Support报错:Failed to delete old Unity Android Supprtinstallation files
  5. Windows动态定义模板类对象
  6. iOS The binary you uploaded was invalid
  7. ADS仿真5_LNA设计
  8. html表白程序源码_表白程序源码html_程序员表白代码html (1)
  9. Android入门,android基础开发
  10. 随机效应与固定效应面板数据回归
  11. 刀图案c语言,刀符号图案大全 | 手游网游页游攻略大全
  12. 查看文件的SHA256校验值
  13. 【doris】V1.2.2安装部署单机版or集群版
  14. 【Java基础】二、大厂都开始重视的基础很重要吗?快来加入基础的学习,巩固一下细枝末角,刷刷面试题吧
  15. qq2013聊天记录在哪个文件夹?QQ2013聊天记录存放位置
  16. 互联网公司招聘--阿里巴巴--运营专员--2016年笔试题
  17. 洛谷P2357 守墓人
  18. 如何用vscode替代xshell
  19. 用百度访问受限的MSN space空间
  20. Saturn vip

热门文章

  1. 随手记获2亿美元C轮融资,随手记投资安全吗?
  2. C++ char类型
  3. mac 上安装git
  4. vxe-table vxe-pager 如何使用分页,自定义分页
  5. C#开发 ActiveX 小票打印控件
  6. 阿里云 icp 备案流程(光速入门篇)
  7. 在windows11环境下如何通过主机名ping通其它系统
  8. Shor’s algorithm
  9. 企业招聘UI设计常见面试题分享
  10. 上古卷轴3晨风职业_上古卷轴3晨风详尽指引攻略_游戏_腾讯网