exkmp(Z 函数)_算法
JueFan 一只绝帆

exkmp(Z 函数)

代码很像 manacher,思路也很像。

作用是求一个串和每个后缀的 lcplcp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
inline void Z(char *s, int n) {
z[1] = n;
for (int i = 2, l = 0, r = 0; i <= n; i++) {
if (i <= r) z[i] = min(z[i-l+1], r - i + 1);
while (i + z[i] <= n && s[i+z[i]] == s[z[i]+1]) ++z[i];
if (i + z[i] - 1 > r) l = i, r = i + z[i] - 1;
}
}

inline void exkmp(char *s, int n, char *t, int m) {
Z(t, m);
for (int i = 1, l = 0, r = 0; i <= n; i++) {
if (i <= r) p[i] = min(z[i-l+1], r - i + 1);
while (i + p[i] <= n && s[i+p[i]] == t[p[i]+1]) ++p[i];
if (i + p[i] - 1 > r) l = i, r = i + p[i] - 1;
}
}

维护 ziz_i,表示 ii 开始的后缀与 11 开始的后缀的 lcplcp,在求的过程中我们动态维护 l,rl,r 表示 rr 最大的已匹配的 lcplcp

在求新的 zz 的时候,我们直接利用已有信息,将其初始化为 min(zil+1,ri+1)\min(z_{i-l+1},r-i+1),然后暴力匹配即可,由于暴力匹配成功必定会使得 rr 变大,所以均摊可证复杂度。

注意 z1z_1 初始化为 nn,求 zz 时从 22 开始枚举。

同理,我们可以对求出了 zz 数组的串与另一个串的每个后缀求 lcplcp

 评论
评论插件加载失败
正在加载评论插件
由 Hexo 驱动 & 主题 Keep
总字数 231.7k 访客数 访问量