图解AC自动机

图解AC自动机

前言:

  • 我们引出这样一个问题:

    • 我想知道字符串\(t\)在字符串中\(s\)出现多少次/有没有出现?
    • 那我们可以使用kmp算法求出\(t\)的next数组,之后\(O(n)\)匹配求解即可。
  • 那如果把问题升级一下呢?
    • 想知道字符串\(t_1,t_2,...,t_n\)在字符串\(s\)中出现了多少次/有没有出现?
    • 这时候再用\(kmp\)算法,复杂度将达到\(O(n^2)\),非常慢了。
    • 这时候我们需要AC自动机。
  • AC自动机用于求解多个模式串与一个文本串的匹配问题。
  • AC自动机需要提前知道所有需要匹配的字符串
  • 可以想象成trie树上kmp。

开始图解:

假设说我们的模式串分别为:\(abcd,abd,bcd,cd\)。

第一步:创建trie树

  • 没啥好说的,建立trie就行了呗。

  • 其中红色节点代表一个字符串的结尾。

第二步:构建失配指针(最重要的一步)

  • 这一步的目的和kmp算法中求nex数组的目的是类似的。
  • 对于kmp算法来说,是求next;对于AC自动机来说,是求fail指针。
  • \(fail(i):\)以\(i\)节点为结尾的串的后缀与其他串有最大公共长度的前缀的结尾编号。
  • 可能看到这里比较懵逼,没关系,模拟一下就好了。
  • 首先看第一个字符串:\(abcd\),不存在任何一个其他子串的前缀与\(abcd\)相匹配。
  • 但是\(bcd\)与\(abcd\)的后缀\(bcd\)相匹配,这是匹配到的最长的情况,于是\(abcd\)上的\(d\)的\(fail\)指针指向\(bcd\)上的\(d\)。
  • 这时候再去看看\(fail\)的定义,是不是觉得清晰了一些呢?

  • 那么自然\(bcd\)上的\(d\)会指向\(cd\)上的\(d\),\(abcd\)上的子串\(abc\)的\(c\)会指向\(bcd\)上的\(c\)。
  • 同样应该也能理解\(root\)的所有直接子节点的\(fail\)指针指向\(root\)。
  • 如果没有找到任何一个前缀与当前串的任何一个后缀相等,那么\(fail\)指针指向\(root\)节点。
  • 这和kmp的nex数组第一位为0道理相同。(假设字符串数组以1开头)
  • 我们画出完整的\(fail\)指针:

  • 与kmp原理相同,fail指针跳到的地方的前面的子串就不用比较了。
  • 接下来我们看看当前节点要是匹配不下去了怎么办?
  • 比如说尝试匹配\(abcde\),\(abcd\)都顺利的匹配了,这是\(d\)没有\(e\)这个子节点,那么就直接跳到\(d\)的\(fail\)指针\(bcd\)上面的\(d\),他也没有子节点\(e\),那就继续直到根节点,那就没有了。

  • \(e\)为虚线,实际上不存在。
  • 而且应该也可以发现,构建\(fail\)指针是一个\(bfs\)的过程。
  • 那匹配的过程其实就相当于是取文本串在\(trie\)树上一层一层的遍历比如说我的文本串是\(abcd\),那么他就会沿着\(trie\)树到\(trie\)树上的\(abcd\),然后根据失配指针跳到\(bcd\)的\(d\),如果\(bcd\)的\(d\)是一个模式串的结尾(在这里显然是),那就统计上答案。

例题:

原文地址:https://www.cnblogs.com/zxytxdy/p/12231818.html

时间: 2024-11-06 12:46:25

图解AC自动机的相关文章

强势图解AC自动机

本篇文章主要详细介绍$AC$自动机的$fail$指针: 如果有什么不完善的地方,请联系我$qwq$ 前置知识: 1.建议学一下$kmp$算法 2.$Trie$ 导入: AC自动机是用来解决多模板匹配问题的,但是,如果就单纯的把每个模板串拼接在一起,或者单个单个匹配的话,肯定是会超时的,而它的思想是把所有的模式串建立一颗$Trie$,然后用文本串来匹配,那么我们就必须在这颗$Trie$树上进行快速跳转来优化,于是,AC自动机就诞生了 重点:fail指针到底是什么? 我们先来思考一个问题,加入我们按

hdu 5955 Guessing the Dice Roll 【AC自动机+高斯消元】

hdu 5955 Guessing the Dice Roll [AC自动机+高斯消元] 题意:给出 n≤10 个长为 L≤10 的串,每次丢一个骰子,先出现的串赢,问获胜概率. 题解:裸的AC自动机,求匹配到终止结点的概率,用 高斯消元?一开始不知道怎么建方程组,直接举个例子吧: Input: 1 2 2 1 1 2 1 图解: x0原本概率就是1,然后还要加上其他结点走向它的概率,,这样最后算下来是大于1的,现在还是觉得怪怪的... 1 #include <cstdio> 2 #inclu

【算法】AC自动机/AC算法 - 多模式串快速匹配

AC自动机 Accepted Aho-Corasick 性质 AC自动机/AC算法(Aho-Corasick automaton),是著名的多模式串匹配算法. 前置知识 字典树(重要) KMP算法(了解Next数组的作用) 典例与算法复杂度分析 典型例题是:给定一个主串 S,给定多个模式串 T,问主串 S 中存在多少个给定的模式串 在KMP算法中,一个长度为n的主串一个长度为m的模式串的复杂度为 O(n+m) 而如果直接照搬KMP算法到这种题型下,模式串处理一次就需要匹配一次 如果有t个模式串,

暑假集训day9补充(AC自动机)

推荐网站http://blog.csdn.net/niushuai666/article/details/7002823 AC自动机嘛,此AC(aho-corasick)非彼AC(Accepted). 我也不是很会解释 有一题是必须打的hdu2222. #include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int mn=

ac自动机基础模板(hdu2222)

In the modern time, Search engine came into the life of everybody like Google, Baidu, etc. Wiskey also wants to bring this feature to his image retrieval system. Every image have a long description, when users type some keywords to find the image, th

HDU 2825 Wireless Password AC自动机+dp

训练赛第二场的I题,上完体育课回来就把这题过了,今天训练赛rank1了,还把大大队虐了,而且我还过了这道题 (虽然我也就过了这道题...),第一次在比赛中手写AC自动机还带dp的,心情大好. 给一个字符串集合,求包含该集合超过K个字符的,长度为L的字符串的个数. 显然是在AC自动机上跑dp,设dp[u][L][k]表示当前在结点u,还要走L步,当前状态为k的个数.一开始第三维表示的是包含k个字符串,但是题目要求不含重复的,那就只能状压了.转移为dp[u][L][k]+=dp[v][L-1][nk

HDU 2896-病毒侵袭(ac自动机)

题意: 给定多个模式串,每给一个母串,输出包含模式串的编号,最后输出包含模式串的母串的数量. 分析: ac自动机模板 #include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <st

hdu2222 Keywords Search &amp; AC自动机学习小结

传送门:http://http://acm.hdu.edu.cn/showproblem.php?pid=2222 思路:AC自动机入门题,直接上AC自动机即可. 对于构建AC自动机,我们要做的只有三件事: 1)构建字典树 2)构建失败指针 3)构建trie图(这道题好像不做这一步也能A...但是这一步不做是会被卡成O(n^2)的...) 1)第一步还是比较好理解的 根是虚根,边代表字母,那么根到终止节点的路径就是一个字符串,这样对于前缀相同的字符串我们就可以省下存公共前缀的空间. 加入一个模式

hdoj 2896 病毒侵袭(AC自动机)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2896 思路分析:题目为模式匹配问题,对于一个给定的字符串,判断能匹配多少个模式:该问题需要静态建树,另外需要对AC自动机的模板加以修改, 对于每个匹配的模式的最后一个单词的fail指针指向root,即可实现一个字符串进行多次模式匹配: 代码如下: #include <queue> #include <cstdio> #include <cstring> #include &