單模式匹配 KMP 演算法 簡易版學習筆記

dengchengyu發表於2024-10-19

KMP

字首函式

\(S_i\) 為字串 \(S\) 的第 \(i\) 個位置。

我們設 \(\pi(i)\) 表示字串以 \(i\) 結尾的字首的最長公共前字尾的長度。

這裡的前字尾都指的是真字首、真字尾。

怎麼 \(O(n)\) 求出 \(\pi(i)\)

性質:相鄰的 \(\pi\) 至多增加 1。

因此, 若 \(s[\pi(i)+1]=s[i+1]\) 時,\(\pi(i+1)=\pi(i)+1\)

如果失配,我們要找到 \(i\) 字首的第二長的公共前字尾,然後再次比較。以此類推。

那麼

\[[s_1s_2s_3s_4]...[s_{i-3}s_{i-2}s_{i-1}s_{i}]s_{i+1} \]

如果 \(\pi(i)=4\),即 \(s[1...4]=s[i-3...i]\)

而第二長的公共前字尾長度 \(j\),假如 \(j=2\),那麼 \(s[1...2]=s[i-1...i]\)

由於 \(s[1...4]=s[i-3...i]\),那麼 \(s[i-1...i]=s[3...4]\),所以 \(s[1...2]=s[3...4]\)

所以第二長的公共前字尾長度是字首 \(\pi(i)\) 的最長公共前字尾長度,即 \(\pi(\pi(i))\)

所以如果 \(\pi(i)+1\) 失配,那麼就找到 \(\pi(\pi(i))+1\),然後是 \(\pi(\pi(\pi(i)))+1\dots\)

到最後找到 \(1\),若不相等則 \(\pi(i+1)=0\)

KMP 演算法

對於文字串 \(s\) 和模式串 \(t\) 匹配,可以求出字串 \(t+\#+s\) 的字首函式,其中 \(\#\) 是一個額外字元,然後就能知道 \(s\) 每個字首能否與 \(t\) 匹配。

相關文章