Z 函数

简单记一下,避免忘记。

z 函数

对于字符串 \(S\),我们将 \(z(i)\) 定义为从 \(i\) 开始的后缀与 \(S\) 的最长公共前缀的长度。

\(O(n)\) 求出 z 函数

我们添加一个分隔符,将 \(S\) 的真正下标变为从 1 开始。此时显然 \(z(1)=n\)

我们需要 \(r\) 最大的匹配串 \(S[l:r]\) ,即为当前最大的 \(l+z(l)-1\)

如果 \(i > r\),显然此时任何之前的 \(z(j)\) 都无法对其提供贡献,所以只能从 \(0\) 开始求。

如果 \(i \le r\),由于 \(S[l:r]\)\(S\) 的前缀匹配,所以 \(S[i-l+1:r-l+1]=S[i:r]\)。但我们并不知道 \(S\) 的前缀与 \(S[i:r]\) 的关系。

根据 z 函数的定义我们可知:\(S[1:1 + z(i-l+1)-1] = S[i-l+1:i-l+1+z(i-l+1)-1]\)

所以实际上我们能确定的相同的只有 \(z(i-l+1)\) 的长度相同。

我们还需要额外考虑一件事:\(i+z(i-l+1)-1\) 是有可能大于 \(r\) 的。但此时我们连第一个等式都不确定了,所以大于的部分并不确定相不相等。所以 \(z(i)\) 最大初始化长度不能超过 \(r-i+1\)

注意求出 \(z(i)\) 后更新 \(l\)\(r\)

posted @ 2022-11-23 20:43  _maze  阅读(278)  评论(0编辑  收藏  举报