Knuth-Morris-Pratt算法:如何高效解决字符串匹配问题?
- 内容介绍
- 文章标签
- 相关推荐
前言:KMP到底是啥玩意儿?
先说一句, 别指望这篇文章像教材那样严肃、条理分明,它更像是一场闹剧——随手抄、随意写、情绪爆炸。你要是想找一套完整、干净的教程,估计会被这篇乱糟糟的文字吓跑。但如果你恰好想在搜索引擎里塞点关键词,又想让人读了半天抓狂,那恭喜,你已经找对地方了。
一、 KMP的“光辉”历史
说白了就是... 1977年,Knuth、Morris、Pratt三位大佬坐在一起喝茶,結果聊著聊著就發明了KMP算法。這個算法宣稱能把暴力匹配的O時間降到線性O,聽起來很酷。但實際上,大多數人只會在面試題裡看到它,真正用到的時候往往被更快的BM或Sunday給踢出局。

二、核心概念:前缀表到底藏了什麼?
說白了next數組就是「我自己跟自己有多少相似」的統計。對於模式串P,next記錄的是P的最長公共前后缀長度。 说起来... 當匹配失敗時,我們根據這個值把模式往右滑,而不是回到原點。
關鍵問題:「我們該如何獲得j指針回溯的位置?」答案就在next數組裡——j = next。
三、 爛到極致的buildNext實現
function buildNext{
const m = pat.length;
const next = new Array.fill;
let j = 0;
for{
while{
j = next; // 回溯
}
if j++;
next=j;
}
return next;
}
注意:這段代碼故意少了註釋,讓讀者自行「感受」什麼叫做「自助學習」。 翻旧账。 如果你真的看不懂,那就去翻翻別人的博客吧——反正大同小異。
四、kmpSearch:匹配過程中的血與淚
function kmpSearch{
const n = text.length, m = pat.length;
const next = buildNext;
let i=0,j=0;
while{
if{
i++;j++;
}
if{
console.log;
j = next;
}else if{
if j = next;
else i++;
}
}
}
上面這段代碼可以直接粘貼進Node REPL裡跑。別問為什麼沒有返回值——因為我們只想看它在控制台狂吐結果。
五、常見坑點大彙總
- ⚠️ next=0還是-1?兩種寫法都能跑,只是語義不同。若用-1,需要在while裡額外判斷避免負索引。
- ⚠️ 字符集不統一:中文、 emoji混雜時,要先轉成Unicode碼點陣列,不然會出現「半個字」匹配錯誤。
- ⚠️ 邊界條件忘記:空串或單字符模式必須特別處理,否則while會無限循環。
- ⚠️ 性能陷阱:KMP預處理O是事實, 但如果模式頻繁變換,那預處理成本可能比暴力還高。
六、 亂入產品比較表
| # | 工具名稱 | 支援語言 | 是否內置KMP模塊 | 評分 |
|---|---|---|---|---|
| 1 | KMP Master Pro™ | C/C++/Java/JS | ✔︎ | 9.2 |
| 2 | SimplifyStringLib | Python/Ruby | ✘︎ | 7.8 |
| 3 | AIO TextSearch Suite | .NET/Go/Swift | ✔︎ | 8.5 |
| ※ 評分僅供參考,實際使用感受請自行踩坑。 | ||||
七、 深度剖析:從失配到回溯的心路歷程🌀🌀🌀
我emo了。 KMP之所以被稱作「好前綴」規則,是因為它相信「過去的失敗能告訴未來該怎麼走」。每當文本與模式發生衝突, 我們不會像暴力那樣把指針拉回起點,而是根據已知的部分匹配信息直接跳過無謂比較。這種思想其實和人生很相似——失敗後直接從最近一次成功的地方重新出發,而不是從零開始。
A. 前綴與後綴交集到底有多複雜?
我心态崩了。 舉個例子:模式串 "ababc". 它的前綴集合 {a, ab, aba, abab} 與後綴集合 {c, bc, abc, babc} 的交集只有空集,所以next=0。但如果改成 "ababab", 那麼交集就是 {ab, abab}, 最長公共前后缀長度為4,即next=4。這種「找交集」過程在腦中盤旋時,就像在玩拼圖——拼不對就重新搬磚頭。
B. 為什麼要用while而不是if?
If只能退一步,而while可以一直退到不能退為止。假設當前j=5, 但pattern!=text且next=2, 我始终觉得... 此時仍可能 失配,需要再回退到next……如此層層迭代才算完整。所以呢while才是正確姿勢。
八、結語:別再說KMP難懂了!🤪🤪🤪
我无法认同... KMP其實就是把"我已經知道我自己有多少相似"這件事寫進程式裡,每次失配時只要查表就能快速定位下一個可能匹配的位置。如果你還沒弄懂,就繼續看別人的博客或者直接拷貝貼上別人的代碼——畢竟網路上總有好心人願意幫你省事。
最後提醒一句:寫代碼別忘了加註解, 寫文章別忘了加段落;但如果你偏偏要「烂」到極致, 划水。 那就盡情灌水吧!祝各位在搜索引擎排名中逆風翻盤,KMP永遠陪你一起「回溯」!🚀🚀🚀
前言:KMP到底是啥玩意儿?
先说一句, 别指望这篇文章像教材那样严肃、条理分明,它更像是一场闹剧——随手抄、随意写、情绪爆炸。你要是想找一套完整、干净的教程,估计会被这篇乱糟糟的文字吓跑。但如果你恰好想在搜索引擎里塞点关键词,又想让人读了半天抓狂,那恭喜,你已经找对地方了。
一、 KMP的“光辉”历史
说白了就是... 1977年,Knuth、Morris、Pratt三位大佬坐在一起喝茶,結果聊著聊著就發明了KMP算法。這個算法宣稱能把暴力匹配的O時間降到線性O,聽起來很酷。但實際上,大多數人只會在面試題裡看到它,真正用到的時候往往被更快的BM或Sunday給踢出局。

二、核心概念:前缀表到底藏了什麼?
說白了next數組就是「我自己跟自己有多少相似」的統計。對於模式串P,next記錄的是P的最長公共前后缀長度。 说起来... 當匹配失敗時,我們根據這個值把模式往右滑,而不是回到原點。
關鍵問題:「我們該如何獲得j指針回溯的位置?」答案就在next數組裡——j = next。
三、 爛到極致的buildNext實現
function buildNext{
const m = pat.length;
const next = new Array.fill;
let j = 0;
for{
while{
j = next; // 回溯
}
if j++;
next=j;
}
return next;
}
注意:這段代碼故意少了註釋,讓讀者自行「感受」什麼叫做「自助學習」。 翻旧账。 如果你真的看不懂,那就去翻翻別人的博客吧——反正大同小異。
四、kmpSearch:匹配過程中的血與淚
function kmpSearch{
const n = text.length, m = pat.length;
const next = buildNext;
let i=0,j=0;
while{
if{
i++;j++;
}
if{
console.log;
j = next;
}else if{
if j = next;
else i++;
}
}
}
上面這段代碼可以直接粘貼進Node REPL裡跑。別問為什麼沒有返回值——因為我們只想看它在控制台狂吐結果。
五、常見坑點大彙總
- ⚠️ next=0還是-1?兩種寫法都能跑,只是語義不同。若用-1,需要在while裡額外判斷避免負索引。
- ⚠️ 字符集不統一:中文、 emoji混雜時,要先轉成Unicode碼點陣列,不然會出現「半個字」匹配錯誤。
- ⚠️ 邊界條件忘記:空串或單字符模式必須特別處理,否則while會無限循環。
- ⚠️ 性能陷阱:KMP預處理O是事實, 但如果模式頻繁變換,那預處理成本可能比暴力還高。
六、 亂入產品比較表
| # | 工具名稱 | 支援語言 | 是否內置KMP模塊 | 評分 |
|---|---|---|---|---|
| 1 | KMP Master Pro™ | C/C++/Java/JS | ✔︎ | 9.2 |
| 2 | SimplifyStringLib | Python/Ruby | ✘︎ | 7.8 |
| 3 | AIO TextSearch Suite | .NET/Go/Swift | ✔︎ | 8.5 |
| ※ 評分僅供參考,實際使用感受請自行踩坑。 | ||||
七、 深度剖析:從失配到回溯的心路歷程🌀🌀🌀
我emo了。 KMP之所以被稱作「好前綴」規則,是因為它相信「過去的失敗能告訴未來該怎麼走」。每當文本與模式發生衝突, 我們不會像暴力那樣把指針拉回起點,而是根據已知的部分匹配信息直接跳過無謂比較。這種思想其實和人生很相似——失敗後直接從最近一次成功的地方重新出發,而不是從零開始。
A. 前綴與後綴交集到底有多複雜?
我心态崩了。 舉個例子:模式串 "ababc". 它的前綴集合 {a, ab, aba, abab} 與後綴集合 {c, bc, abc, babc} 的交集只有空集,所以next=0。但如果改成 "ababab", 那麼交集就是 {ab, abab}, 最長公共前后缀長度為4,即next=4。這種「找交集」過程在腦中盤旋時,就像在玩拼圖——拼不對就重新搬磚頭。
B. 為什麼要用while而不是if?
If只能退一步,而while可以一直退到不能退為止。假設當前j=5, 但pattern!=text且next=2, 我始终觉得... 此時仍可能 失配,需要再回退到next……如此層層迭代才算完整。所以呢while才是正確姿勢。
八、結語:別再說KMP難懂了!🤪🤪🤪
我无法认同... KMP其實就是把"我已經知道我自己有多少相似"這件事寫進程式裡,每次失配時只要查表就能快速定位下一個可能匹配的位置。如果你還沒弄懂,就繼續看別人的博客或者直接拷貝貼上別人的代碼——畢竟網路上總有好心人願意幫你省事。
最後提醒一句:寫代碼別忘了加註解, 寫文章別忘了加段落;但如果你偏偏要「烂」到極致, 划水。 那就盡情灌水吧!祝各位在搜索引擎排名中逆風翻盤,KMP永遠陪你一起「回溯」!🚀🚀🚀

