AC自动机

\(AC\)自动机

概念

\(KMP\)类似,\(AC\)自动机也是用来处理字符串匹配问题的。但\(AC\)自动机处理的是多模式串问题(问在一篇有\(m\)个单词的文章中,有多少个不同的单词在其中出现)。

算法实现

  1. 建立\(Trie\)

    我们将所有模式串构建出一颗\(Trie\)

  2. 匹配

    当模式串只有一个时,\(AC\)自动机的匹配方式与\(KMP\)相同。

    现在匹配是在\(Trie\)上进行的,我们令主串\(S\),模式串\(T\)。假设现在匹配到了\(u\)节点,即我们得到了一个从根到\(u\)构成的字符串,这是其中一个模式串的前缀\(T[1\cdots j]\),也是主串的一段字串\(S[i-j+1\cdots i]\)

    1. \(S[i + 1]\)\(T[j+1]\)能够匹配,也就是\(u\)节点存在字符为\(S[i+1]\)的边(指向\(v\)),那么\(j+1,u=v\)

    2. 若匹配失败,也就是\(u\)节点不存在字符为\(S[i+1]\)的边。这时我们需要找到另外一个串,使得它有尽量长的前缀与根到\(u\)组成的字符串相等(\(T'[1\cdots k]=T[j-k+1\cdots j]\),其中\(T'[1\cdots k]\)对应着\(Trie\)中根到某个节点\(v\)组成的字符串)。此时我们令\(u=v,j=k\),继续匹配\(S[i + 1]\)\(T’[j+1]\)

    我们发现,新的\(u\)与主串\(S\)无关(与\(KMP\)一样)。我们完全可以预处理出一个数组\(nextu[u]\),表示当匹配到\(u\)节点而无法再匹配时,满足\(T'[1\cdots k]=T[j-k+1\cdots j]\)的最深节点\(v\)

  3. 建立\(nextu\)

    建立\(nextu\)的策略与\(KMP\)\(P\)的建立类似。显然\(nextu[u]\)的深度小于\(u\)的深度,所以我们令\(v,u\)分别表示字符串\(T'[1\cdots j],T[1\cdots i]\),其中\(v\)\(u\)的前缀且\(nextu[u]=v\),现在\(u\)的边指向节点\(x\)

    1. \(T'[j+1]=T[i+1]\),设\(v\)的相同字母边为\(y\)\(nextu[x]=y\)
    2. \(T'[j+1]\neq[i+1]\),我们令\(v=nextu[v]\),继续重复步骤\(1\),直到匹配或跳到空节点(\(nextu[x]=0\))。

例题

给定\(n\)个长度不超过\(50\)的由小写字母组成的单词,以及一个文章(只有一个字符串)。问多少个单词在文中出现。

对于这道题,我们只需要在查询的时候记录每一个未访问的节点作为末尾的次数。

posted @ 2025-03-10 22:48  nightmare_lhh  阅读(14)  评论(0)    收藏  举报