1. 程式人生 > >史上最好理解的KMP演算法

史上最好理解的KMP演算法

暴力匹配演算法

首先,我假設你已經是一個已經懂暴力匹配演算法的人了。
但是暴力匹配演算法有一個問題:當你知道你的目標串和搜尋串不匹配的時候,它已經附帶了一些資訊。
比如在如圖匹配,實際上目標串已經匹配到了第七個字元D
這裡寫圖片描述
如果接下來你還是把A往後移動一格,實際上你浪費了這次匹配。你應該把A往後移動四格才對。
而利用到了這個資訊的就是KMP演算法:

已知部分匹配表的KMP演算法

首先我們先給出一個部分匹配表:
這裡寫圖片描述
這個表你先用著,具體怎麼生成接下來會說。

Step1:

這裡寫圖片描述
已知空格和D不匹配但是前面六格是匹配的。查表可知,對後一個匹配字元B對應的部分匹配值為2,根據如下公式

移動位數=已匹配的字元數-對應的部分匹配值

因為6-2=4,所以搜尋詞移動4位。

再來試一次:

這裡寫圖片描述
因為空格與c不匹配,搜尋詞還要繼續往後移動。這時,已匹配的字元數為2(“AB”),對應的部分匹配值為0.所以,移動位數=2-0,結果為2,於是將搜尋詞後移兩位。
依次類推。
而匹配串是怎麼產生的呢?

部分匹配表的產生

首先來了解字首和字尾的概念
這裡寫圖片描述
“字首”指除了最後一個字元以外,一個字串的全部頭部組合;”字尾”指除了第一個字元以外,一個字串的全部尾部組合。
這裡寫圖片描述
產生依據:

  - “A”的字首和字尾都為空集,共有元素的長度為0;
  - “AB”的字首為[A],字尾為[B],共有元素的長度為0;
  - “ABC”的字首為[A, AB],字尾為[BC, C],共有元素的長度0;
  - “ABCD”的字首為[A, AB, ABC],字尾為[BCD, CD, D],共有元素的長度為0;
  - “ABCDA”的字首為[A, AB, ABC, ABCD],字尾為[BCDA, CDA, DA, A],共有元素為”A”,長度為1;
  - “ABCDAB”的字首為[A, AB, ABC, ABCD, ABCDA],字尾為[BCDAB, CDAB, DAB, AB, B],共有元素為”AB”,長度為2;
  - “ABCDABD”的字首為[A, AB, ABC, ABCD, ABCDA, ABCDAB],字尾為[BCDABD, CDABD, DABD, ABD, BD, D],共有元素的長度為0。

直觀來看是兩張圖:
這裡寫圖片描述
這裡寫圖片描述
綠色是相同的字串

java程式碼

但是看到求部分匹配表的java程式碼,我們又一次懵逼了。

public int[] getNext(String b)
{
    int len=b.length();
    int j=0;

    int next[]=new int[len+1];//next表示長度為i的字串字首和字尾的最長公共部分,從1開始
    next[0]=next[1]=0;

    for(int i=1;i<len;i++)//i表示字串的下標,從0開始
    {//j在每次迴圈開始都表示next[i]的值,同時也表示需要比較的下一個位置
while(j>0&&b.charAt(i)!=b.charAt(j))j=next[j]; if(b.charAt(i)==b.charAt(j))j++; next[i+1]=j; } return next; }

為什麼計算部分匹配表的時候不按套路出牌啊?為啥程式碼這麼簡單啊。
但是我們要知道,部分匹配表也是有資訊可以利用的。
如圖
這裡寫圖片描述
當我們知道第j(此處為5)個字元的部分匹配值為i(此處為1)的時候,求第j+1(6)個字元的部分匹配值,我們只需要判斷第i+1(2)個字元是不是和第j+1(6)是不是相等就可以了。如果相等,則第j+1(6)的部分匹配值必為i+1(2)。
所以程式碼有一行是:

        if(b.charAt(i)==b.charAt(j))j++;
        next[i+1]=j;

但是如果這兩個字元不相等呢?

從前面來找子前後綴

1 、如果要存在對稱性,那麼對稱程度肯定比前面這個的對稱程度小,所以要找個更小的對稱,這個不用解釋了吧,如果大那麼就繼承前面的對稱性了。

2 、如果還是不相等,要找更小的對稱,必然在對稱內部還存在子對稱,而且這個必須緊接著在子對稱之後。

while(j>0&&b.charAt(i)!=b.charAt(j))j=next[j];

相關推薦

最好理解KMP演算法

暴力匹配演算法 首先,我假設你已經是一個已經懂暴力匹配演算法的人了。 但是暴力匹配演算法有一個問題:當你知道你的目標串和搜尋串不匹配的時候,它已經附帶了一些資訊。 比如在如圖匹配,實際上目標串已經匹配到了第七個字元D 如果接下來你還是把A往後

最好程序員的職業規劃:五年從程序員到架構師之路!

最好 淘寶 好的項目 com 職業 消息 關於 技術學 收獲 第一部分:對於參加工作一年以內的同學。恭喜你,這個時候,你已經擁有了一份Java的工作。這個階段是你成長極快的階段,而且你可能會經常加班。但是加班不代表你就可以松懈了,永遠記得我說的那句話,從你入行那一刻起,你就

循序漸進,深入理解KMP演算法

KMP演算法是三位大牛:D.E.Knuth、J.H.Morris和V.R.Pratt同時發現的。其中第一位就是《計算機程式設計藝術》的作者! KMP演算法要解決的問題就是在字串(也叫主串)中的模式(pattern)定位問題。說簡單點就是我們平時常說的關鍵字搜尋。模式串就是關鍵字(接下來

你知道最好用的APP是哪一些嗎?Python來告訴你!

    第三、可以找到 App 的 歷史版本。很多人喜歡用最新版本的 App,一有更新就馬上升級,但是現在很多 App 越來越功利、越更新越臃腫、廣告滿天飛,倒不如 迴歸本源,使用體積小巧、功能精簡、無廣告的早期版本。   私信菜鳥00

最好的LDA(線性判別分析)教程

一、前言 最近由於研究需要,要用到線性判別分析(LDA)。於是找了很多資料來看,結果發現大部分講的都是理論知識,因此最後還是看的一知半解,後來終於找到了個英文的文件,作者由PCA引入LDA,看過後豁然開朗,主要是文件中有詳細的例子,為了保持原版在此就直接貼

配置最好用的Vim

下載地址 http://www.vim.org/scripts/script.php?script_id=273 版本 4.4 安裝 在 ~/.vim 目錄下解壓taglist_xx.zip 手冊 :help taglist.txt 在Windows平臺上用過Source Insight看程式的人肯定很熟

從DFA角度理解KMP演算法

KMP 演算法 KMP(Knuth-Morris-Pratt)演算法在字串查詢中是很高效的一種演算法,假設文字字串長度為n,模式字串長度為m,則時間複雜度為O(m+n),最壞情況下能提供線性時間執行時間保證。 《演算法導論》和其他地方在講解KMP演算法的時候

vim ide:配置最好用的Vim

下載地址 http://www.vim.org/scripts/script.php?script_id=273 版本 4.4 安裝 在 ~/.vim 目錄下解壓taglist_xx.zip 手冊 :help taglist

KMP之一:從頭到尾徹底理解KMP演算法(2014年8月1日版)

作者:July 時間:最初寫於2011年12月,2014年7月21日晚10點 全部刪除重寫成此文。 1. 引言     本KMP原文最初寫於2年多前的2011年12月,因當時初次接觸KMP,思路混亂導致寫也寫得非常混亂,如此,留言也是“罵聲”一片。所以一直想找機會重新寫下KMP,但苦於一直以來對KMP的理

五年從程式設計師到架構師!這是我見過最好的程式設計師職業規劃

作者:大齊老師 連結:https://www.jianshu.com/p/4afeba725b2e 來源:簡書 第一部分: 對於參加工作一年以內的同學。恭喜你,這個時候,你已經擁有了一份Java的工作。這個階段是你成長極快的階段,而且你可能會經常加班。但是加班不代

簡單理解KMP演算法

KMP演算法是迄今為止最為高效的字串匹配演算法。當然,在KMP演算法出現之前,有關字串的匹配問題當然經過了一個漫長的探索過程。從一開始最簡單的樸素字串匹配演算法,到Rabin-Karp演算法,再到有限自動機演算法等等,可以說任何一個偉大演算法的誕生都不可能是一朝

最好程式設計師的職業規劃:五年從程式設計師到架構師!

第一部分: 對於參加工作一年以內的同學。恭喜你,這個時候,你已經擁有了一份Java的工作。這個階段是你成長極快的階段,而且你可能會經常加班。但是加班不代表你就可以鬆懈了,永遠記得我說的那句話,從你入行那一刻起,你就要不停的學習。在這一年裡,你至少需要看完《Ja

透徹理解KMP演算法

好好打下字串演算法基礎。本篇通俗、透徹地解釋線性時間複雜度的字串匹配演算法:KMP演算法。 之前寫過KMP演算法,但時間久了回顧起來還是要花點兒時間,覺得需要進一步加深;現在就試圖徹底吃透它。若是感興趣豆友們能得到一點點的幫助就更好了~ 別忘了點個贊:-) KMP 演算法的

最好的20本敏捷開發書籍

Top 20 Best Agile Development Books, Ever I recently created a Top 100 Best Software Engineering Books, Ever . I created that list us

Echarts圖示寬度變成100px,讓圖表寬度隨著父元素自動適應,Vue實時監聽寬度的變化,這可能是最好的解決方案!

最近工作中element後臺管理使用Echarts圖表,本後臺專案分圖表模式和列表模式,使用display控制顯示隱藏,這樣就引出了本文的問題。   問題1:Echarts圖表寬度變成100px? 問題2:怎麼讓Echarts圖表寬度隨著父元素自動適應?      網上對於這兩個

最容易理解的《十大經典演算法(動態圖展示)》

十大經典排序演算法 部分內容引用自:https://www.cnblogs.com/onepixel/articles/7674659.html 感謝作者貢獻,如需刪除請聯絡本人! 0、排序演算法說明 0.1 排序分類   非線性時間比較類排序:通過比較來

KMP演算法——基於Youtube外國小哥講解及其Github程式碼的理解

前言 本篇文章是在看了CSDN上那些“大佬”們對KMP演算法的長篇大論後仍然看不懂,而在Youtube上看了一外國小哥講解的視訊後有所領悟,同時想給廣大受苦群眾分享外國小哥的講解而寫的文章。 外國小哥關於KMP演算法的Java模板 各位可以直接瀏覽以上網

最通俗易懂的理解雲計算

雲計算 阿裏雲 阿裏雲幸運券 “雲計算”這三個字相信你一定聽過無數遍了,那麽我想問問你,“雲計算”到底是什麽?你能回答出來嗎?首先我們聽到雲計算三個字時,感覺非常高大上,高不可測的,新技術等等,如果你沒有接觸過的,感覺離我們很遠,很不生活化,不像滴滴打車這麽生活化的應用軟件。 目錄導航:1、雲計算

KMP演算法淺顯理解

說明:轉載 KMP演算法看懂了覺得特別簡單,思路很簡單,看不懂之前,查各種資料,看的稀裡糊塗,即使網上最簡單的解釋,依然看的稀裡糊塗。 我花了半天時間,爭取用最短的篇幅大致搞明白這玩意到底是啥。 這裡不扯概念,只講演算法過程和程式碼理解: KMP演算法求解什麼型別問題 字串匹配。給

KMP演算法最淺顯理解

說明 KMP演算法看懂了覺得特別簡單,思路很簡單,看不懂之前,查各種資料,看的稀裡糊塗,即使網上最簡單的解釋,依然看的稀裡糊塗。  我花了半天時間,爭取用最短的篇幅大致搞明白這玩意到底是啥。  這裡不扯概念,只講演算法過程和程式碼理解: KMP演算法求解什麼型別問題