zoukankan      html  css  js  c++  java
  • 从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.红色结点表示接受态.

    显然,查找时只需顺着链照下来,插入只需边查找边插入.

    (删除只需除去接受态,或此时在它没有子结点时删除到它的最近接受态父结点)

    好懂好写高效率.

    AC自动机

    AC自动机是一种基于Trie的数据结构.它是一个真正的自动机.

    AC自动机,简单地说就是加了一些奇怪东西的Trie.

    (powered by cocoa....Cacoo)

    实线表示Trie上的路径,虚线表示Fail指针.

    Fail指针是什么呢?当你在这个结点上时,对于下一个字符失匹配时你要走的路.很类似于KMP的next数组.

    它的定义也是基本一样的.最长有相同前缀的后缀(的那个前缀的最后一个字母结点的指针).

    使用起来更是一样.计算也是一样的.顺着fat(s[p-1])的fail(next[k])跳到可以匹配为止.

    简单吧?和KMP很像.

    那么问题又来了.怎么输出呢?

    我们再画个图想想.

    原来,顺着Fail指针一直走下去即可啊...

    那么我们就有了用AC自动机匹配的算法.

    匹配第一个`A`,从root往下找

    找到匹配,A的匹配加一.向下寻找下一个字符找到Null.

     

    因Fail指针回跳到root.寻找字符C.

    寻找字符B.不是接受态,继续.

    A是一个接受态.沿着Fail指针走回去输出结果.

    -------------------

    匹配C失跳.

    ------------------------------

    ...........................

    ...................最终

    结果

    构造一个AC自动机

    那么,如何构造一个AC自动机呢?

    显然可以在每加入一个结点时沿着它的父亲的Fail指针走,走到第一个有相同字符子结点的找到那个子结点,将Fail指向那个结点;如果到root还没找到有同字符子结点,将Fail指向root.

    这是在线的做法.离线当然可以用BFS解决,这样保证了当一个结点被处理时它的父亲那层的结点已经处理完.Fail结点最近也只可能在父亲那层.复杂度应与在线办法相同.

    Update: 犯了个SB错,AC自动机不可在线.原因Fail指针可能改变.

    图表地址:https://cacoo.com/diagrams/xqj6UFk5zcllgHGW

  • 相关阅读:
    P1309 瑞士轮 (吸氧了)
    P1158 导弹拦截
    腾讯笔试题 构造回文(LCS问题)
    蓝桥杯之大臣的旅费(两次dfs)
    蓝桥杯之买不到的数目(数学公式或缩小范围+暴力)
    蓝桥杯之翻硬币(思维,找规律,贪心)
    蓝桥杯之 连号区间数(巧妙遍历)
    蓝桥杯之剪格子(经典dfs)
    蓝桥杯之带分数(全排列+暴力)
    面试题之O(n)内旋转字符串
  • 原文地址:https://www.cnblogs.com/tmzbot/p/4418709.html
Copyright © 2011-2022 走看看