关闭

AC自动机基本介绍

标签: AC自动机字典树
470人阅读 评论(0) 收藏 举报
分类:

                                                           AC自动机

    转载自:http://blog.csdn.net/niushuai666/article/details/7002823
  AC自动机模板在我的后面一篇博客,也就是hdu2222入门题。

AC自动机简介: 

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

AC自动机的构造:

1.构造一棵Trie,作为AC自动机的搜索数据结构。

2.构造fail指针,使当前字符失配时跳转到具有最长公共前后缀的字符继续匹配。如同 KMP算法一样, AC自动机在匹配时如果当前字符匹配失败,那么利用fail指针进行跳转。由此可知如果跳转,跳转后的串的前缀,必为跳转前的模式串的后缀并且跳转的新位置的深度(匹配字符个数)一定小于跳之前的节点。所以我们可以利用 bfs在 Trie上面进行 fail指针的求解。

3.扫描主串进行匹配。

AC自动机详讲:

我们给出5个单词,say,she,shr,he,her。给定字符串为yasherhs。问多少个单词在字符串中出现过。

一、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]是否是单词。

构造的Trie为:


二、构造失败指针

用BFS来构造失败指针,与KMP算法相似的思想。

首先,root入队,第1次循环时处理与root相连的字符,也就是各个单词的第一个字符h和s,因为第一个字符不匹配需要重新匹配,所以第一个字符都指向root(root是Trie入口,没有实际含义)失败指针的指向对应下图中的(1),(2)两条虚线;第2次进入循环后,从队列中先弹出h,接下来p指向h节点的fail指针指向的节点,也就是root;p=p->fail也就是p=NULL说明匹配序列为空,则把节点e的fail指针指向root表示没有匹配序列,对应图-2中的(3),然后节点e进入队列;第3次循环时,弹出的第一个节点a的操作与上一步操作的节点e相同,把a的fail指针指向root,对应图-2中的(4),并入队;第4次进入循环时,弹出节点h(图中左边那个),这时操作略有不同。由于p->next[i]!=NULL(root有h这个儿子节点,图中右边那个),这样便把左边那个h节点的失败指针指向右边那个root的儿子节点h,对应图-2中的(5),然后h入队。以此类推:在循环结束后,所有的失败指针就是图-2中的这种形式。


三、扫描

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

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

 对照上图,看一下模式匹配这个详细的流程,其中模式串为yasherhs。对于i=0,1。Trie中没有对应的路径,故不做任何操作;i=2,3,4时,指针p走到左下节点e。因为节点e的count信息为1,所以cnt+1,并且讲节点e的count值设置为-1,表示改单词已经出现过了,防止重复计数,最后temp指向e节点的失败指针所指向的节点继续查找,以此类推,最后temp指向root,退出while循环,这个过程中count增加了2。表示找到了2个单词she和he。当i=5时,程序进入第5行,p指向其失败指针的节点,也就是右边那个e节点,随后在第6行指向r节点,r节点的count值为1,从而count+1,循环直到temp指向root为止。最后i=6,7时,找不到任何匹配,匹配过程结束。


到此,AC自动机入门知识就讲完了。HDU 2222入门题必须果断A掉,反正我是参考别人代码敲的。。。

AC自动机貌似还有很多需要优化的地方,等把基础搞定之后再学习一下怎么优化吧。。

模板在我的后面一篇博客,也就是hdu2222入门题。

1
0
查看评论

多模式串匹配之AC自动机算法(Aho-Corasick算法)简介与C语言程序实现源码参考

一、概述 AC自动机算法全称Aho-Corasick算法,是一种字符串多模式匹配算法。该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一。AC算法用于在一段文本中查找多个模式字符串,即给你很多字符串,再给你一段文本,让你在文本中找这些串是否出现过,出现过多少次,分别在哪里出现。 该算法...
  • zhoubl668
  • zhoubl668
  • 2012-03-05 16:19
  • 4465

python使用esmre代替ahocorasick实现ac自动机[多模匹配]

Toggle navigation Home saltstack ansible zabbix docker python Golang web开发 运维开发 运维 文艺 python使用esmre代...
  • Real_Myth
  • Real_Myth
  • 2015-11-24 15:48
  • 2010

Python算法实践——AC自动机

初来乍到CSDN,如果要说写博客的原因,想想平日学习编程语言看了那么多别人的博客,也该试着自己写一写了。第一次写博客写不知从何下笔,就从最近写的一个自动机开始吧。
  • backkom_lory
  • backkom_lory
  • 2016-12-26 23:01
  • 1257

Trie图 & AC自动机初学(1)

题目来源于:Hihocoder 时间限制:20000ms 单点时限:1000ms 内存限制:512MB 描述 前情回顾 上回说到,小Hi和小Ho接受到了河蟹先生伟大而光荣的任务:河蟹先生将要给与他们一篇从互联网上收集来的文章,和一本厚厚的河蟹词典,而他们要...
  • qq_32036091
  • qq_32036091
  • 2016-05-08 10:13
  • 1234

Python3实现AC自动机

AC自动机是一种多模匹配算法,所谓多模匹配,就是模式串有多个。其主要的步骤分为三步: 1.用模式串建立字典树,字典树(Trie树)是一种变种的哈希数,存放字符串非常方便,查找效率也比较高。字典树中存放的字符串即是从根到叶子路径上所有结点值,每次插入新的字符串,在遍历字符串的同时,从根结点开始查找,...
  • Fitz1318
  • Fitz1318
  • 2017-01-15 16:57
  • 836

AC自动机

今天看了AC自动机,原理大致理解,但是模版代码有些地方不了解,大致可以解决这类问题: 给你一个字典(包含n个不重复的单词),然后给你一串连续的字符串文本(长为len),问你该文本里面的哪些位置正好出现了字典中的某一个或某几个单词?输出这些位置以及出现的单词。解决的是长文本的多模板匹配问题。它是KM...
  • qq_35739903
  • qq_35739903
  • 2018-01-29 23:22
  • 13

AC自动机详解

请务必保证已经学会了kmp和Trie,如果对kmp和Trie还不熟练,请先阅读这两篇博客进行学习: kmp:http://blog.csdn.net/hao_zong_yin/article/details/75165028 Trie:http://blog.csdn.net/hao_zong_y...
  • hao_zong_yin
  • hao_zong_yin
  • 2017-08-26 20:22
  • 118

AC自动机 - 关于Fail指针

fail指针可以说是AC自动机里最难理解的东西,怎样更好的理解AC自动机的fail指针? 先来看一幅图: 看这幅图上的fail指针是怎么构造的. 树上的词分别是: { he , hers , his , she} 按图所示分成3层。看到第三层,是"she",其中: ...
  • u013371163
  • u013371163
  • 2017-03-05 17:17
  • 675

ac自动机最详细的讲解,让你一次学会ac自动机。

在没学ac自动机之前,觉得ac自动机是个很神奇,很高深,很难的算法,学完之后发现,ac自动机确实很神奇,很高深,但是却并不难。 我说ac自动机很神奇,在于这个算法中失配指针的妙处(好比kmp算法中的next数组),说它高深,是因为这个不是一般的算法,而是建立在两个普通算法的基础之上,而这两个算法就...
  • creatorx
  • creatorx
  • 2017-05-02 19:51
  • 16857

基于python3的杭电HDU ACM AC自动机

先放几个图 RunnerUp资料页起因 规划和思路 一开始规划成了2个模块一个答案爬取模块和一个OJ操作模块 模块 终于开始写代码啦 1 login模块 2 submit模块 3 getdiscuss模块 4 getsolved 5 getbaidu 6 autorun 最后 1 改进方向 2 源码...
  • jjhfen00
  • jjhfen00
  • 2016-03-09 23:54
  • 560
    个人资料
    • 访问:67243次
    • 积分:1816
    • 等级:
    • 排名:千里之外
    • 原创:105篇
    • 转载:38篇
    • 译文:0篇
    • 评论:3条
    最新评论