專題:字串

Lu_xZ發表於2024-07-24

KMP

幾個定義:

  • \(pre_i = s[1, i]\)\(suf_i = s[n - i + 1, n]\)
  • \(p\)\(s\)border 當且僅當 \(pre_p = suf_p\),特殊的,\(n\) 一定是 \(s\) 的 border。
  • \(p\)\(s\)週期 當且僅當 \(\forall i > p,\ s_i = s_{i - p}\),特殊的,\(n\) 一定是 \(s\) 的 週期。
  • 週期 \(p\)\(s\)迴圈節 當且僅當 \(p \mid n\),特殊的,\(n\) 一定是 \(s\) 的 迴圈節。

定理1\(p\)\(s\) 的週期等價於 \(n - p\)\(s\) 的 border。

證明:\(q\)\(s\) 的 border:\(s_1 = s_{n - q + 1}, \cdots, s_q = s_n\)。不難得到 \(n - q\)\(s\) 的週期。

注意:border 沒有二分性。

border 的暴力求法:列舉 \(1 \le i \le n\),檢驗是否有 \(pre_i = suf_i\),時間複雜度 \(O(n^2)\)

優雅的暴力:雜湊 \(O(1)\) 判定前字尾相等。缺點:常數大,會被卡。

定理2\(s\) 的 border 的 border 也是 \(s\) 的 border。

證明:畫個圖很好理解。

推論:求 \(s\) 的所有 border 等價於求所有字首的最大 border。

\(p = n\)\(s\) 的最大 border,然後我們要求 \(p\) 的最大(不為本身) border,化歸為子問題。

Next 陣列

定義:\(ne_i\) 表示 \(pre_i\) 的最大非平凡 border,其中 \(ne_1 = 0\)

不難發現 \(pre_i\) 的所有 border 減 \(1\) 一定是是 \(pre_{i - 1}\) 的 border。

因此我們依次檢查 \(ne_{i - 1}, ne_{ne_{i - 1}}\cdots\) (即 \(pre_{i - 1}\) 的所有 border)的下一位是否等於 \(s_i\),以此遞推出 \(ne_i\)

時間複雜度分析:

相關文章