KMP, Knuth-Morris-Pratt

KMP 是字串匹配演算法。
核心做法是先建立 LPS(Longest Prefix Suffix)陣列,
在 mismatch 時避免回頭重複比較。


為什麼 KMP 比暴力法快

暴力法在 mismatch 時,主字串指標常需要回退或重複掃描。

KMP 透過 LPS 知道:

因此主字串索引 i 不回退,整體可達線性時間。


LPS 是什麼

lps[j] 表示:
pattern[0..j] 這段字串中,
「最長相等的真前綴與真後綴」的長度。

例:pattern = "ABABCABAB"

lps = [0,0,1,2,0,1,2,3,4]


Matching 流程(概念)

  1. text[i] == pattern[j],兩者都前進
  2. 若 mismatch 且 j > 0,令 j = lps[j-1]
  3. 若 mismatch 且 j == 0,只前進 i
  4. j == len(pattern),找到一個匹配位置,之後 j = lps[j-1] 繼續找下一個

Python 範例

def build_lps(pattern: str):
    lps = [0] * len(pattern)
    length = 0
    i = 1

    while i < len(pattern):
        if pattern[i] == pattern[length]:
            length += 1
            lps[i] = length
            i += 1
        elif length > 0:
            length = lps[length - 1]
        else:
            lps[i] = 0
            i += 1

    return lps


def kmp_search(text: str, pattern: str):
    if not pattern:
        return [0]

    lps = build_lps(pattern)
    i = j = 0
    ans = []

    while i < len(text):
        if text[i] == pattern[j]:
            i += 1
            j += 1
            if j == len(pattern):
                ans.append(i - j)
                j = lps[j - 1]
        elif j > 0:
            j = lps[j - 1]
        else:
            i += 1

    return ans


print(kmp_search("ABABDABACDABABCABAB", "ABABCABAB"))
[10]

複雜度

其中:


常見錯誤


相關筆記

Powered by Forestry.md