Loading

AC自动机-算法详解

What's Aho-Corasick automaton?

  一种多模式串匹配算法,该算法在1975年产生于贝尔实验室,是著名的多模式匹配算法之一。

  简单的说,KMP用来在一篇文章中匹配一个模式串;但如果有多个模式串,需要在一篇文章中把出现过的模式串都匹配出来,就需要Aho-Corasick automaton算法了。

My Understanding About Aho-Corasick automaton

    我的理解:Aho-Corasick automaton = Trie + KMP

  在KMP算法中,匹配单个字符的时候,我们只需要按照文本线性的扫一遍,然后中途失配的时候,next数组会引导k回溯到正确的位置进行下一步的匹配。

  但是多个模式串的时候要怎么匹配呢?Trie树不就是一个多模式的匹配吗,如果我们将KMP和Trie数结合起来,是不是会有意想不到的效果呢?

  有了这些思考,AC自动机算法就这样产生了。

  在AC自动机中,我们首先将每一个模式串插入到Trie树中去,建立一棵Trie树,然后构建fail指针,fail指针,顾名思义,就是当匹配失败的时候,用来引导k回溯的一个插穿在Trie树的各个节点之间的一些指针,就和KMP算法中的next数组是一样的道理。

  关于fail指针的构建,推荐看一下李翔大神的PPT。

  ppt下载链接:

    http://wenku.baidu.com/view/93af2c936bec0975f465e2f1.html

1.构建Trie树

  

  

2.在Trie树上构建fail指针

  

  

 

 

 

 

 

 

 

 

构建完fail指针后,我们就用文章来对这棵Trie树进行匹配了。

  匹配过程分两种情况:

  • 当前字符匹配,表示从当前节点沿着树边有一条路径可以到达目标字符,此时只需沿该路径走向下一个节点继续匹配即可,目标字符串指针移向下个字符继续匹配;
  • 当前字符不匹配,则去当前节点fail指针所指向的字符继续匹配,匹配过程随着指针指向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时,找不到任何匹配,匹配过程结束。

匹配过程总结:

从root节点开始,每次根据读入的字符沿着自动机向下移动。

当读入的字符,在分支中不存在时,递归走Fail指针。如果走Fail指针走到了root节点,则跳过该字符,处理下一个字符。
因为AC自动机是沿着输入文本的最长后缀移动的,所以在读取完所有输入文本后,最后递归走Fail指针,直到到达根节点,这样可以检测出所有的模式。
这个过程和KMP算法的匹配也是非常相似,当然这一步就非常灵活了,我们需要通过多做题来提高熟练度。

Time Complexity Analyse

假设有N个模式串,平均长度为L;文章长度为M。

建立Trie树:O(N*L)

建立fail指针:O(N*L)

模式匹配:O(M*L) (注:之所以要乘以一个L,是因为在统计的时候需要顺着链回溯到root结点)

所以,总时间复杂度为:O( (N+M)*L )

Some Good Selection Of Standard Exercise

Entry:

synthesize problems:

posted @ 2014-09-30 23:18  北岛知寒  阅读(5262)  评论(0编辑  收藏  举报