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\)。
時間複雜度分析: