AC自动机初步

概述

应用场景:多模字符串匹配问题

KMP解决的问题是两个字符串之间的互相匹配,而如果有多个字符串要和一个字符串进行匹配呢?如果还用KMP的话,复杂度依然上天,所以,一个正常的想法是在KMP的基础上堆数据结构。

所以AC自动机=在Trie树上跑KMP,它其中也存在失配数组,与KMP类似。

初见

AC自动机的基础是Trie树。和Trie树不同的是,树中的每个结点除了有指向孩子的指针(或者说引用),还有一个fail指针,它表示输入的字符与当前结点的**所有孩子结点都不匹配时**(注意,不是和该结点本身不匹配),自动机的状态应转移到的状态(或者说应该转移到的结点)。fail指针的功能可以类比于KMP算法中next数组的功能。

我们现在来看一个用目标字符串集合{abd,abdk, abchijn, chnit, ijabdf, ijaij}构造出来的AC自动机

-----By nullzx

也就是说,f函数所指向的点,与当前点之间有最长后缀。

每个结点的fail指针表示由根结点到该结点所组成的字符序列的所有后缀 和 整个目标字符串集合(也就是整个Trie树)中的所有前缀 两者中最长公共的部分。 by nullzx

这里与KMP却有异曲同工之妙。

应用

假设已经处理出了f函数,那么该如何应用呢?

我们知道\(f[]\)表示的是当前点的最长后缀,那么,AC自动机的运行就要进行以下步骤(设cur为Trie树中的光标):

  1. 要匹配的字符串光标往后移一位
  2. 检测\(cur\)的后继状态中是否存在合法情况(\(pa[cur][S[i]-'a']?\))。
  3. 如果存在,则将所有的包含该后缀的点的后缀都统计一遍。
for(int i=0,j=0;i<l;i++){
    j=pa[j][S[i]-'a'];
    for(int k=j;k;k=f[k])
        if(val[k])ans+=val[k],val[k]=0;
}

还是要具体例子具体分析,应用三言两语是讲不清楚的。

fail数组

重点还是在这个fail数组的处理上。

先上代码:

void get_fail(){
    queue<int>Q;
    for(int i=0;i<26;i++){
        if(pa[0][i]!=0){
            f[pa[0][i]]=0;
            Q.push(pa[0][i]);
        }
    }
    while(!Q.empty()){
        int u=Q.front();Q.pop();
        for(int i=0;i<26;i++){
            if(pa[u][i]!=0){
                f[pa[u][i]]=pa[f[u]][i];
                Q.push(pa[u][i]);
            }
            else pa[u][i]=pa[f[u]][i];
        }
    }
}

其实这就是板子,对照上面的图,多模拟几下应该很好理解。。。(太懒了,我受不了了。。。)

原文地址:https://www.cnblogs.com/zryabc/p/10427896.html

时间: 2024-10-06 03:18:00

AC自动机初步的相关文章

hdu2222 Keywords Search(AC自动机初步)

题目大意: 给出多个模式串和一个主串,求多少个模式串在主串中出现过. 传送门 这是一道AC自动机的模板题. 在学习AC自动机之前,首先要学习WA自动机.TLE自动机和MLE自动机(雾 AC自动机是一种多模式串匹配算法. AC自动机概述: *fail指针:指向失配时的匹配节点: 1)构建字典树 2)初始化fail指针: 一条$fail$指针链可以理解为一个串连所有后缀相同的字符串的链表,并且所有链表的末端都指向trie的根.我们定义沿着节点$v$的$fail$指针走到根部的路径为v的trie链表.

中文分词系列(二) 基于双数组Tire树的AC自动机

秉着能偷懒就偷懒的精神,关于AC自动机本来不想看的,但是HanLp的源码中用户自定义词典的识别是用的AC自动机实现的.唉-没办法,还是看看吧 AC自动机理论 Aho Corasick自动机,简称AC自动机,要学会AC自动机,我们必须知道什么是Trie,也就是字典树.Trie树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高.之

暑假集训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 &

从Trie谈到AC自动机

ZJOI的SAM让我深受打击,WJZ大神怒D陈老师之T3是SAM裸题orz...我还怎么混?暂且写篇`从Trie谈到AC自动机`骗骗经验. Trie Trie是一种好玩的数据结构.它的每个结点存的是字母,因此得名`字母树`. 出一张图让大家感受下. (image powered by SaiBu NaoCu) 上面那是一棵插入了 ape,app,applicant,application,bake,ban,banana 等词的Trie.红色结点表示接受态. 显然,查找时只需顺着链照下来,插入只需