ac自动机
前置知识:
- t r i e 树 trie树 trie树
- K M P KMP KMP
作用:
- 查询一个字符串,在一堆字符串中的匹配情况。
- 利用 f a i l fail fail树还可以解决一个字符串的前缀,在其他字符串中的出现情况。
- 还有一堆神奇作用。
结构:
- 分为两个部分: f a i l fail fail树和 a c ac ac自动机
a c ac ac自动机部分:
- 本质是一个 t r i e trie trie树,里面包含所有字符串,即每个点都是这些字符串中的一个前缀。
- t r i e trie trie树上有 f a i l fail fail边,表示失配时应该回到哪个状态继续匹配。一个点 x x x的 f a i l [ x ] fail[x] fail[x]表示 r o o t root root到 f a i l [ x ] fail[x] fail[x]这条路径所代表的字符串前缀,是 r o o t root root到 x x x这条路径所代表的字符串前缀的 最长的 能找到的 后缀(就是类似 K M P f a i l KMPfail KMPfail)。
f a i l fail fail树部分:
- f a i l fail fail树就是 f a i l fail fail边建出来的一棵树(儿子指向父亲),因为每个点(除了 r o o t root root)都有且仅有一条 f a i l fail fail边。
- f a i l fail fail树上每个点都是 t r i e trie trie上的一个点,所以都代表一个前缀。
- f a i l fail fail树上的祖先都是子孙的后缀(相当于是前缀的后缀)。
- 对于 f a i l fail fail树上的一个点 x x x, f a [ x ] fa[x] fa[x]所代表的前缀是 x x x所代表的前缀的最长可找到的后缀。
实现过程:
- 建出 t r i e trie trie树,由短到长依次找 f a i l fail fail,通过 b f s bfs bfs实现。
- 一个点 x x x的 f a i l [ x ] fail[x] fail[x]是 f a i l [ f a [ x ] ] fail[fa[x]] fail[fa[x]]的一个 a [ x ] a[x] a[x]儿子,如果没有则找 f a i l [ f a i l [ f a [ x ] ] ] fail[fail[fa[x]]] fail[fail[fa[x]]]的一个 a [ x ] a[x] a[x]儿子,以此类推,一直找到 r o o t root root。
- 为了时间优化,我们直接将 x x x一个 t r i e 树 trie树 trie树上不存在的 n e x t next next赋成 f a i l [ x ] fail[x] fail[x](或者 f a i l [ f a i l [ x ] ] … fail[fail[x]] \dots fail[fail[x]]…)的 n e x t next next。用父亲更新儿子,由上到下更新就会将常数降低很多。这样建出来的就是 t r i e trie trie图。
例题:
- 电脑游戏 NKOJ1962
- 数数[SDOI2014] NKOJ2842
- 单词[TJOI2013] NKOJ9217
- 阿狸打字机[NOI2011] NKOJ3388
- 具体见AC自动机—helang。