网站优化

网站优化

Products

当前位置:首页 > 网站优化 >

Knuth-Morris-Pratt算法:如何高效解决字符串匹配问题?

GG网络技术分享 2026-04-17 06:35 0


前言:KMP到底是啥玩意儿?

先说一句, 别指望这篇文章像教材那样严肃、条理分明,它更像是一场闹剧——随手抄、随意写、情绪爆炸。你要是想找一套完整、干净的教程,估计会被这篇乱糟糟的文字吓跑。但如果你恰好想在搜索引擎里塞点关键词,又想让人读了半天抓狂,那恭喜,你已经找对地方了。

一、 KMP的“光辉”历史

说白了就是... 1977年,Knuth、Morris、Pratt三位大佬坐在一起喝茶,結果聊著聊著就發明了KMP算法。這個算法宣稱能把暴力匹配的O時間降到線性O,聽起來很酷。但實際上,大多數人只會在面試題裡看到它,真正用到的時候往往被更快的BM或Sunday給踢出局。

深入解析 Knuth-Morris-Pratt 算法:字符串匹配的高效解决方案

二、核心概念:前缀表到底藏了什麼?

說白了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模塊評分
1KMP Master Pro™C/C++/Java/JS✔︎9.2
2SimplifyStringLibPython/Ruby✘︎7.8
3AIO 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永遠陪你一起「回溯」!🚀🚀🚀



提交需求或反馈

Demand feedback