感觉和 KMP 关系不大啊
Z函数(拓展KMP)
定义
故名思意, Z 函数是个函数,若我们定义一个长度为 $n$ 的字符串以第 $i$ 个字符开头,第 $j$ 个字符结尾(下标从 $1$ 开始)的子串为 $s[i \sim j]$ ,再定义 $LCP(x, y)$ 代表字符串 $x, y$ 的最长公共前缀长度,那么,有 $ Z[i] = LCP(s[i \sim n], s[0 \sim n])$ ,即 $Z[i]$ 表示以 $i$ 开头的后缀与原串的最长公共前缀
求法
直接求显然不好,类似 kmp 考虑用已有的信息,结论是,我们同时维护已与前缀匹配上的位置为 $s[l, r]$ ,如有多个(肯定有多个)取 $r$ 最大
当枚举到 $i$ 时,把 $Z[i]$ 初始化为 $\min(Z[i - l + 1], r - i + 1)$ (要保证 $i \le r$ ),而每次计算完后用 $Z[i]$ 跟新 $l, r$ ,关于正确性,对图理解很显然:
考虑时间复杂度,由于 $l, r$ 单调,直接用初始化匹配的复杂度是线性的,而暴力匹配时,原串的每个字符最多被匹配一次,所以是 $O(n)$ 的
注意, $Z[1]$ 要单独处理
代码
1 |
|