在計算機科學中,Knuth-Morris-Pratt字符串查找算法(簡稱為KMP算法)可在一個主文本字符串S內查找一個模式串P的出現位置。此算法通過運用對這個模式串在不匹配時本身就包含足夠的信息來確定下一個匹配將在哪里開始的發現,從而避免重新檢查先前匹配的字符。
今天寫完kmp的題, 發現又想不通了, 這個next數組實在是太繞了, 去跑步的路上不禁一直在想, 終於恍然大悟了! 感覺十分有必要寫一篇解釋, 用自己的話說說kmp以及這個next. 一方面加深一下印象, 另一方面希望給偶然看到的人一點點啟發 (
簡介
首先, 如果我們用傳統的方式來匹配這個字符串, 會得到如下的過程:
如果用KMP算法, 將減少無用的挪動 :
這么看可能還看不出什么, 如果我們稍微變化一下就可以看到KMP算法的巨大優勢 :
對於上圖這種匹配, 普通的暴力算法將遠遠落后於kmp
kmp工作機制
如果你不知道"前后綴" 也許以下的圖能更好的幫助理解
上圖來源於這里
匹配過程
為什么是剛好跳轉到next[i]
比如上面這個圖中, 接下來我們會將失配位置移動到P[2]也就是A的地方(右移兩下), 如果我們少移, 是不可能匹配的, 不然的話公共前后綴長度會比當前的值大
next數組的編程求法
重點 : 弄明白j回溯的原理
建議對照代碼觀看 :
int i = 0, j = -1;
while(i < s.size()) {
if(s[i] == s[j] || j==-1) {
i++;
j++;
next.push_back(j);
}
else {
j = next[j]; // 如果s[i]!=s[j]說明匹配失敗, 回到上一級公共前后綴處
}
}
我們列出兩個相鄰的指針i和j, 初始指在數組前和0號元素的位置
接下來我列出從0開始求出next數組的圖示
這里再附上兩個寫的不錯的鏈接
http://www.ruanyifeng.com/blog/2013/05/Knuth–Morris–Pratt_algorithm.html
https://www.bilibili.com/video/BV1Px411z7Yo?t=1068
好累啊