参考链接:

https://blog.csdn.net/bestsort/article/details/82947639#commentBox

https://blog.csdn.net/niushuai666/article/details/7002823

AC自动机简介:
首先简要介绍一下AC自动机:Aho-Corasick automation,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一。一个常见的例子就是给出n个单词(这n个单词,我们称它为模式串),再给出一段包含m个字符的文章(我们称它为主串),让你找出有多少个单词在文章里出现过。要搞懂AC自动机,先得有字典树Trie和KMP模式匹配算法的基础知识。KMP算法是单模式串的字符匹配算法,AC自动机是多模式串的字符匹配算法。

ac自动机时间复杂度:
假设有N个模式串,平均长度为L;文章长度为M。 建立Trie树:O(N*L) 建立fail指针:O(N*L) 模式匹配:O(M*L) 所以,总时间复杂度为:O( (N+M)*L )。

AC自动机构造:

1、首先用n个单词构造一颗字典树

2、为树上的每一个节点设一个失败指针(代码中用fail[]数组来表示),这个失败指针和KMP算法有点类似。用KMP算法来找的时候如果匹配失败会通过next数组跳到下一个位置进行匹配。失败指针也是这个用途,它就是此次匹配失败后跳到下一个位置进行下一次匹配

3、扫描主串进行匹配

具体AC自动机构造:

一、Trie
首先我们需要建立一棵Trie。但是这棵Trie不是普通的Trie,而是带有一些特殊的性质。
首先会有3个重要的指针,分别为p, p->fail, temp
1.指针p,指向当前匹配的字符。若p指向root,表示当前匹配的字符序列为空。(root是Trie入口,没有实际含义)。
2.指针p->fail,p的失败指针,指向与字符p相同的结点,若没有,则指向root。
3.指针temp,测试指针(自己命名的,容易理解!~),在建立fail指针时有寻找与p字符匹配的结点的作用,在扫描时作用最大,也最不好理解。

对于Trie树中的一个节点,对应一个序列s[1...m]。此时,p指向字符s[m]。若在下一个字符处失配,即p->next[s[m+1]] == NULL,则由失配指针跳到另一个节点(p->fail)处,该节点对应的序列为s[i...m]。若继续失配,则序列依次跳转直到序列为空或出现匹配。在此过程中,p的值一直在变化,但是p对应节点的字符没有发生变化。在此过程中,我们观察可知,最终求得得序列s则为最长公共后缀。另外,由于这个序列是从root开始到某一节点,则说明这个序列有可能是某些序列的前缀。
再次讨论p指针转移的意义。如果p指针在某一字符s[m+1]处失配(即p->next[s[m+1]] == NULL),则说明没有单词s[1...m+1]存在。此时,如果p的失配指针指向root,则说明当前序列的任意后缀不会是某个单词的前缀。如果p的失配指针不指向root,则说明序列s[i...m]是某一单词的前缀,于是跳转到p的失配指针,以s[i...m]为前缀继续匹配s[m+1]。
对于已经得到的序列s[1...m],由于s[i...m]可能是某单词的后缀,s[1...j]可能是某单词的前缀,所以s[1...m]中可能会出现单词。此时,p指向已匹配的字符,不能动。于是,令temp = p,然后依次测试s[1...m], s[i...m]是否是单词。

fail指针构造:

首先给定模式串"ash","shex","bcd","sha",然后我们根据模式串建立如下trie树:

然后我们再了解下一步:
ac自动机,就是在tire树的基础上,增加一个fail指针,如果当前点匹配失败,则将指针转移到fail指针指向的地方,这样就不用回溯,而可以路匹配下去了.(当前模式串后缀和fail指针指向的模式串部分前缀相同,如abce和bcd,我们找到c发现下一个要找的不是e,就跳到bcd中的c处,看看此处的下一个字符(d)是不是应该找的那一个)
一般,fail指针的构建都是用bfs实现的
首先每个模式串的首字母(也就是根节点的直系子节点)肯定是指向根节点的

现在第一层bfs遍历完了,开始第二层

(根节点为第0层)第二层a的子节点为s,但是我们还是要从a-z遍历,如果不存在这个子节点我们就让他指向根节点(如下图红色的a)

当我们遍历到s的时候,由于它的父亲节点(即、a)的fail指针指向的节点(即、根)的直系子节点存在s这个节点,我们就让他的fail指针指向他父亲节点(a)的fail指针指向的那个节点()的具有相同字母的子节点(第一层的s),也就是这样(没错fail指针就是这样构造的

按照相同规律构建第二层后,到了第三层的h点,还是按照上面的规则,我们找到h的父亲节点(s)fail指针指向的那个位置(第一层的s)然后指向它所指向的相同字母根->s->h的这个链的h节点,如下图

完全构造好后的树

然后匹配就很简单了,这里以ashe为例
我们先用ash匹配,到h了发现:诶这里ash是一个完整的模式串,好的ans++,然后找下一个e,可是ash后面没字母了啊,我们就跳到hfail指针指向的那个h继续找,还是没有e?再跳,结果当前的h指向的是根节点,又从根节点找,然而还是没有找到e,程序END

扫描主串:

构造好Trie和失败指针后,我们就可以对主串进行扫描了。这个过程和KMP算法很类似,但是也有一定的区别,主要是因为AC自动机处理的是多串模式,需要防止遗漏某个单词,所以引入temp指针。

匹配过程分两种情况:(1)当前字符匹配,表示从当前节点沿着树边有一条路径可以到达目标字符,此时只需沿该路径走向下一个节点继续匹配即可,目标字符串指针移向下个字符继续匹配;(2)当前字符不匹配,则去当前节点失败指针所指向的字符继续匹配,匹配过程随着指针指向root结束。重复这2个过程中的任意一个,直到模式串走到结尾为止。

扫描代码:

 1 int len=strlen(s);
2 int now=root;
3 int res=0;
4 for(int i=0;i<len;++i)
5 {
6 now=next[now][s[i]-'a']; //这个now就保证了我们找的肯定是这个s字符串中的一部分
7 int temp=now; //这就是一直找,找到了就加1,找不到就通过失败指针看其他地方能不能找到
8 while(temp!=root) //尝试这个节点的失败指针能不能找到模式串
9 {
10 res+=ends[temp]; //因为我们要找出来s串中包含几种模式串,所以要有赋值0操作
11 ends[temp]=0;
12 temp=fail[temp];
13 }
14 }
15 return res;

例题:

Keywords Search HDU - 2222 AC自动机板子题

AC自动机算法 && 例题的更多相关文章

  1. AC自动机算法详解

    首先简要介绍一下AC自动机:Aho-Corasick automation,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一.一个常见的例子就是给出n个单词,再给出一段包含m个字符的文章, ...

  2. AC自动机-算法详解

    What's Aho-Corasick automaton? 一种多模式串匹配算法,该算法在1975年产生于贝尔实验室,是著名的多模式匹配算法之一. 简单的说,KMP用来在一篇文章中匹配一个模式串:但 ...

  3. AC自动机算法详解 (转载)

    首先简要介绍一下AC自动机:Aho-Corasick automation,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一.一个常见的例子就是给出n个单词,再给出一段包含m个字符的文章, ...

  4. (转)两种高效过滤敏感词算法--DFA算法和AC自动机算法

    原文:https://blog.csdn.net/u013421629/article/details/83178970 一道bat面试题:快速替换10亿条标题中的5万个敏感词,有哪些解决思路? 有十 ...

  5. AC自动机算法小结

    AC自动机,可惜不能自动AC 转载:飘过的小牛 OIer55242 简介 Aho-Corasick automation 该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一.一个常见的例子就 ...

  6. AC自动机算法

    AC自动机简介:  首先简要介绍一下AC自动机:Aho-Corasick automation,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一.一个常见的例子就是给出n个单词,再给出一段 ...

  7. 转载 - AC自动机算法

    出处:http://blog.csdn.net/niushuai666/article/details/7002823 AC自动机简介:  首先简要介绍一下AC自动机:Aho-Corasick aut ...

  8. AC自动机算法学习

    KMP+TRIE int val[1000100][31],tot; int tr[1000100]; int fail[1000100]; struct AC_Trie{ void clean(){ ...

  9. Aho-Corasick automaton(AC自动机)解析及其在算法竞赛中的典型应用举例

    摘要: 本文主要讲述了AC自动机的基本思想和实现原理,如何构造AC自动机,着重讲解AC自动机在算法竞赛中的一些典型应用. 什么是AC自动机? 如何构造一个AC自动机? AC自动机在算法竞赛中的典型应用 ...

随机推荐

  1. 【Problems】端口被占用 查看是被谁占用并关闭它

    文章目录 Windows Linux 经常在Windows.Linux环境下运行JavaWeb项目,Tomcat的端口被占用了. 端口被占用就查看是被谁占用关闭它就行. Windows 在Window ...

  2. 【Oracle】10g rac如何开启归档和关闭归档

    开启归档: 1.设置想设置的归档的位置,我们这里归档的位置为ASM磁盘组,磁盘组的名称为DATA alter system set log_archive_dest_1='location=+DATA ...

  3. 【DBA】非常好的一个脚本网站

    今天无意间发下了一个特别好的一个oracle脚本的网站.网站地址如下: https://oracle-base.com/dba/scripts 里面都是一些非常实用的脚本.

  4. 基于Dockfile构建JAVA环境网站镜像

    查看本地目录 [root@docker tomcat]# ls apache-tomcat-8.5.16.tar.gz  Dockerfile  jdk-8u91-linux-x64.tar.gz   ...

  5. 使用Spring的RestTemplate进行接口调用

    引自:http://www.zimug.com/ 1.常见的http服务的通信方式 经常使用的方式有HttpClient.OkHttp.RestTemplate.其中RestTemplate是一种更优 ...

  6. python Mysql 多条件查询

    做项目时,遇到一场景,前端至少传入一个参数,最多传入四个参数,根据单参数或者组合参数,从数据库筛选数据. 作为一个小白,思考之,从数学的角度,\(C_4^1 + C_4^2+C_4^3+C_4^4=1 ...

  7. MongoDB 总结

    目录 1. 逻辑结构 2. 安装部署 2.1 系统准备 2.2 mongodb安装 2.2.1 创建所需用户和组 2.2.2 创建mongodb所需目录结构 2.2.3 上传并解压软件到指定位置 2. ...

  8. 笔记 | 吴恩达新书《Machine Learning Yearning》

    这本书共112页,内容不多,偏向于工程向,有很多不错的细节,在此记录一下. 0 书籍获取 关注微信公众号"机器学习炼丹术",回复[MLY]获取pdf 1 测试集与训练集的比例 2 ...

  9. 一种优化递归算法的方法(javascript)

    看书的时候看到了这个比较酷的方法,分享一下. 一.问题描述:代码如下,我们以计算阶乘(factorial)为例,当重复调用factorial(9),factorial(8),factorial(7)的 ...

  10. I/O 复用 multiplexing data race 同步 coroutine 协程

    小结: 1.A file descriptor is considered ready if it is possible to perform the corresponding I/O opera ...