一种用于多模式串匹配的自动机,可以近似看成 $\text{Trie}$ 树上的 $\text{KMP}$ 算法。
给你一个文本串 $S$ 和 $n$ 个模式串 $T_i$,求每个模式串 $T_i$ 在 $S$ 中出现的次数。
建立 $\text{AC}$ 自动机后记录每个节点的访问次数,最后拓扑或建立 $\text{fail}$ 树统计答案。时间复杂度 $O(|S|+\sum_{i=1}^n |T_i|)$。
给定 $n$ 个 $01$ 串 $S_i$,问是否存在无限长串不含任何 $S_i$。
建立 $\text{AC}$ 自动机标记每个 $S_i$ 的终止节点,然后建 $\text{fail}$ 树,显然所有终止节点在 $\text{fail}$ 树中的子树节点均不能访问,于是将其标记。
最后 $\text{dfs}$ 遍历树,在不经过所有标记节点的前提下判定是否存在可以到达的环。注意为保证时间复杂度 $\text{dfs}$ 遍历后也需要标记节点。
总时间复杂度 $O(\sum_{i=1}^n |S_i|)$。
给定一个字符串 $S$,只包含小写字母和 $B,P$ 两个大写字母。
当前初始串 $T$ 为空串,扫描 $S$,如果 $s_i$ 为小写字母,则在 $T$ 末尾加入该字母。
如果 $s_i$ 为 $B$,则删除 $T$ 末尾的一个字母。如果 $s_i$ 为 $P$,则打印 $T$ 。
接下来 $q$ 个询问,每次询问第 $i$ 次打印的字符串在第 $j$ 次打印的字符串中出现的次数。
考虑建 $\text{fail}$ 树,记第 $i$ 次打印的字符串的结尾结点为 $p_i$,第 $j$ 次打印的字符串的结尾结点为 $p_j$。
于是该次询问的答案为 $\text{Trie}$ 树中根节点到 $p_j$ 的路径与 $p_i$ 在 $\text{fail}$ 树中的子树的交集的结点个数。
考虑将所有询问离线到 $\text{Trie}$,然后 $\text{dfs}$ 遍历 $\text{Trie}$ 树同时处理询问。
可以利用 $\text{fail}$ 树上的 $\text{dfs}$ 序以及树状数组维护子树,遍历过程中回溯维护链的性质。
时间复杂度 $O((|S|+q)\log |S|)$。
给定 $n$ 个模式串 $S_i$,问有多少个长度为 $m$ 的文本串至少包含一个模式串。(模式串、文本串只含大写字母)
考虑计算出不含任何模式串的文本串,再用总数减去该值即可得到答案。
接下来标记所有模式串终止位置在 $\text{fail}$ 树上的子节点,显然转移时不能到达标记结点。
最后设 $\text{dp}(i,j)$ 表示当前位于结点 $i$ 且长度为 $j$ 的方案数,暴力转移即可。总时空间复杂度 $O(m\sum_{i=1}^n |S_i|)$。
给定 $n$ 个模式串,每个字符串有一个权值 $v$。要求构造一个长度为 $L$ 的字符串,使得其包含的模式串权值和最大。(包含多个相同模式串结果将累加)
标记所有模式串终止位置在 $\text{fail}$ 树上的子节点,子树可以累加父节点的权值。
最后设 $\text{dp}(i,j)$ 表示当前位于结点 $i$ 且长度为 $j$ 的最大答案,暴力转移。总时空间复杂度 $O(L\sum_{i=1}^n |S_i|)$。
给定 $m$ 个禁止串 $S_i$,求长度为 $n$ 且子串不含任意禁止串的字符串数。
数据保证 $\sum_{i=1}^m |S_i|\le 100,n\le 10^9$。
考虑建立 $\text{fail}$ 树,然后标记所有禁止串终止结点以及其在 $\text{fail}$ 树中的子树。
然后将树边转化为 $\sum_{i=1}^m |S_i|\times \sum_{i=1}^m |S_i|$ 的邻接矩阵 $A$ 来进行状态转移,套用矩阵快速幂即可快速求解,最后答案即为 $\sum A_{0,i}$。
时间复杂度 $O\left((\sum_{i=1}^m |S_i|)^3\log n\right)$。
给定一个 $n\times m$ 的二维文本串和一个 $x\times y$ 的二维模式串,问模式串在文本串中的出现次数。
考虑将模式串按行拆分为 $t_1,t_2\cdots t_x$ 后插入 $\text{AC}$ 自动机,同时进行编号(相同的字符串共用一个编号)。
再将 $t_1,t_2\cdots t_x$ 的编号相连得到一个一维数组 $b$。
同时将文本串按行拆分为 $s_1,s_2\cdots s_n$ 后在 $\text{AC}$ 自动机查询并记录匹配位置的模式串编号,得到一个二维数组 $a$。
二维数组中元素 $a_{i,j}$ 的意义是 $s[i][j-y+1,j]$ 与模式串 $t_{a_{i,j}}$ 匹配。
于是对 $a$ 的每列跑 $\text{KMP}$ 算法记录 $b$ 的出现数即可。时间复杂度 $O(nm+xy)$。
注意上述方法中 $AC$ 自动机起到了降维的作用,且可以拓展到任意维字符串匹配。