1. 程式人生 > >字串匹配的KMP演算法--字首和字尾的詳解

字串匹配的KMP演算法--字首和字尾的詳解

字串匹配是計算機的基本任務之一。

舉例來說,有一個字串"BBC ABCDAB ABCDABCDABDE",我想知道,裡面是否包含另一個字串"ABCDABD"?

許多演算法可以完成這個任務,Knuth-Morris-Pratt演算法(簡稱KMP)是最常用的之一。它以三個發明者命名,起頭的那個K就是著名科學家Donald Knuth。

這種演算法不太容易理解,網上有很多解釋,但讀起來都很費勁。直到讀到Jake Boxer的文章,我才真正理解這種演算法。下面,我用自己的語言,試圖寫一篇比較好懂的KMP演算法解釋。

1.

首先,字串"BBC ABCDAB ABCDABCDABDE"的第一個字元與搜尋詞"ABCDABD"的第一個字元,進行比較。因為B與A不匹配,所以搜尋詞後移一位。

2.

因為B與A不匹配,搜尋詞再往後移。

3.

就這樣,直到字串有一個字元,與搜尋詞的第一個字元相同為止。

4.

接著比較字串和搜尋詞的下一個字元,還是相同。

5.

直到字串有一個字元,與搜尋詞對應的字元不相同為止。

6.

這時,最自然的反應是,將搜尋詞整個後移一位,再從頭逐個比較。這樣做雖然可行,但是效率很差,因為你要把"搜尋位置"移到已經比較過的位置,重比一遍。

7.

一個基本事實是,當空格與D不匹配時,你其實知道前面六個字元是"ABCDAB"。KMP演算法的想法是,設法利用這個已知資訊,不要把"搜尋位置"移回已經比較過的位置,繼續把它向後移,這樣就提高了效率。

8.

怎麼做到這一點呢?可以針對搜尋詞,算出一張《部分匹配表》(Partial Match Table)。這張表是如何產生的,後面再介紹,這裡只要會用就可以了。

9.

已知空格與D不匹配時,前面六個字元"ABCDAB"是匹配的。查表可知,最後一個匹配字元B對應的"部分匹配值"為2,因此按照下面的公式算出向後移動的位數:

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

因為 6 - 2 等於4,所以將搜尋詞向後移動4位。

10.

因為空格與C不匹配,搜尋詞還要繼續往後移。這時,已匹配的字元數為2("AB"),對應的"部分匹配值"為0。所以,移動位數 = 2 - 0,結果為 2,於是將搜尋詞向後移2位。

11.

因為空格與A不匹配,繼續後移一位。

12.

逐位比較,直到發現C與D不匹配。於是,移動位數 = 6 - 2,繼續將搜尋詞向後移動4位。

13.

逐位比較,直到搜尋詞的最後一位,發現完全匹配,於是搜尋完成。如果還要繼續搜尋(即找出全部匹配),移動位數 = 7 - 0,再將搜尋詞向後移動7位,這裡就不再重複了。

14.

下面介紹《部分匹配表》是如何產生的。

首先,要了解兩個概念:"字首"和"字尾"。 "字首"指除了最後一個字元以外,一個字串的全部頭部組合;"字尾"指除了第一個字元以外,一個字串的全部尾部組合。

15.

"部分匹配值"就是"字首"和"字尾"的最長的共有元素的長度。以"ABCDABD"為例,

  - "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。

16.

"部分匹配"的實質是,有時候,字串頭部和尾部會有重複。比如,"ABCDAB"之中有兩個"AB",那麼它的"部分匹配值"就是2("AB"的長度)。搜尋詞移動的時候,第一個"AB"向後移動4位(字串長度-部分匹配值),就可以來到第二個"AB"的位置。

相關推薦

字串匹配KMP演算法--字首字尾

字串匹配是計算機的基本任務之一。 舉例來說,有一個字串"BBC ABCDAB ABCDABCDABDE",我想知道,裡面是否包含另一個字串"ABCDABD"? 許多演算法可以完成這個任務,Knuth-Morris-Pratt演算法(簡稱KMP)是最常用的之一。它以三個發明者命名,起頭的那個K就是著

字串匹配 & KMP演算法

初識KMP 期末的時候學習了KMP演算法,雖然一開始的確聽得是一頭霧水,但是到現在,已經基本懂得了其中的原理,於是在這裡把自己的理解寫出來,再配上自己做的圖示,希望對大家的學習有幫助,要是有什麼疑問或建議,歡迎留言評論。^-^ KMP是一種用於字串匹配的

演算法#15--子字串查詢演算法彙總程式碼

1.演算法彙總 首先,來看一張彙總表,本文會將表裡的每種演算法作詳細介紹。程式碼和邏輯比較長,可以根據目錄跳著看。 2.暴力演算法 在文字中可能出現匹配的任何地方都檢查是否存在。原理很簡單,直接看程式碼就可以懂。 實現程式碼: //暴力子

字串匹配KMP演算法中Next[]陣列求法

int get_nextval(SString T,int &nextval[ ]){            //求模式串T的next函式修正值並存入陣列nextval。            i=1; nextval[1]=0; j=0;            while(i<T[0]){

字串匹配——KMP演算法中的next陣列理解

關於原理就不講了,只說下我對Next陣列的理解,希望可以讓你獲得靈光一閃。 其實最難的就是是j=Next[j];這麼一句話,當時思考了很長時間,終於明白的時候確實很興奮加得意。 #include<cstdio> #include<cstring> v

字串匹配——KMP演算法的Java實現

開始複習演算法,複習到字串這一結構時,一個經典的問題就是兩個字串的匹配問題。 比如:在主串ssdfgasdbababa中找是否存在一個asdba的子串。 傳統方法——暴力匹配 用傳統的方法就是暴力匹配,從主串中一個個地和子串匹配。 最壞的情況下,就是

ELFhash 字串雜湊演算法(以ELFHash

字串雜湊演算法(以ELFHash詳解)   更多字串雜湊演算法請參考:http://blog.csdn.net/AlburtHoffman/article/details/19641123 先來了解一下何為雜湊: 雜湊表是根據設定的雜湊函式H(key)和處

KMP演算法及next陣列

    最近整理筆記時,突然翻出幾年前理解起來困難無比的看毛片(KMP)演算法,筆記中詳述了搜尋過程,圖文並茂,然而在最最重要的next陣列部分卻是一帶而過,於是找出當年的教材,也只是寫了getnext()函式,想著上網找一找圖文並茂的舉例,結果這一找徹底蒙比,眾說紛紜,同

java中加密演算法Base64RSAAndroid

手機的安全重要資訊容易被洩露的方式: 1.會從我們本地洩露     手機中毒等 2.會從伺服器洩露  伺服器人員將資訊賣出去等 3.半路上,網路傳輸的過程中 加密傳輸資料    手機連線WiFi,如果在WiFi上設定監聽資料,將關鍵的資訊攔截下來,就有可能盜取個人重要資訊

快速冪-競賽演算法用法--例題---Hayden's Blog.

在ACM競賽中經常會遇到各種的求冪問題,這種問題一般情況下對應的數字都會很大,所以快速冪就會經常用到,快速冪很好用,就算沒有弄清楚快速冪的原理,只要有模板很快就可以解題。 先說幾個比較重要的公式:

leetcode 214 Shortest Palindrome kmp演算法 字首字尾字串匹配

0 leetcode 214. Shortest Palindrome  本題的描述是一個串前方加上一些字串,使其成為一個迴文串。 形式類似於(新增部分)(迴文部分)(其餘部分),所以我們的目標就是將其迴文部分求出來,或者把他的長度求出來。 如果用暴力解法,那麼問題就變成

字串匹配-BF演算法KMP演算法

宣告:圖片及內容基於https://www.bilibili.com/video/av95949609 BF演算法 原理分析 Brute Force 暴力演算法 用來在主串中查詢模式串是否存以及出現位置     核心就是回溯 如果模式串下標 j 始終沒有到達'\0'則沒有找到

字串匹配 KMP演算法分析

圖片來源於  土豆洋芋山藥蛋 https://blog.csdn.net/qq_33414271/article/details/83789478 1.什麼是KMP演算法? 在主串Str中查詢模式串Pattern的方法中,有一種方式叫KMP演算法 KMP演算法是在模式

字串匹配——樸素演算法KMP演算法

字串匹配(string match)是在實際工程中經常會碰到的問題,通常其輸入是原字串(String)和子串(又稱模式,Pattern)組成,輸出為子串在原字串中的首次出現的位置。通常精確的字串搜尋演算法包括樸素搜尋演算法,KMP, BM(Boyer Moore), sund

ACM-字串-模式串匹配-KMP演算法

在模式匹配演算法中,KMP是比較常見的單模、高效率演算法之一。在討論KMP之前,先看看樸素的匹配演算法為什麼低效。普通的暴力匹配演算法在每一次匹配失敗之後,僅僅下移一位,並且需要重新判斷整個模式串的每一個字元,見下圖: 第一次匹配時,首先會遍歷模式串的每一個字元,但是發現

字串模式匹配KMP演算法

字串模式匹配指的是,找出特定的模式串在一個較長的字串中出現的位置。 樸素的模式匹配演算法很直觀的可以寫出下面的程式碼,來找出模式串在一個長字串中出現的位置。 1: /* 2: 樸素的模式匹配演算法 3: 功能:字串的模式匹配 4: 引數: 5

KMP演算法之NextNextval

KMP演算法是模式匹配專用演算法 它是在已知模式串的next或nextval陣列的基礎上執行的。如果不知道它們二者之一,就沒法使用KMP演算法,因此我們需要計算它們。 KMP演算法由兩部分組成: 第一部分,計算模式串的next或nextval陣列。 第二

字串字首字尾

        字串的字首是指字串的任意首部。比如字串“abbc”的字首有“a”,“ab”,“abb”,“abbc”。同樣,字串的任意尾部是字串的字尾,“abbc”的字尾有“c”,“bc”,“bbc”,“abbc”。現在給出一些字串, 找出每個字串中含字元種類最多的字首或字

ACM水題--字串字首字尾

字串的字首和字尾 Time Limit:1000MS Memory Limit:65536K Total Submit:81 Accepted:22 Description 字串的字首是指字串的任意首部。比如字串“abbc”的字首有“a”,“ab”,“abb”,

演算法資料結構 | 只要30行程式碼,實現快速匹配字串KMP演算法

本文始發於個人公眾號:**TechFlow**,原創不易,求個關注 今天是**演算法資料結構專題**的第29篇文章,我們來聊一個新的字串匹配演算法——KMP。 KMP這個名字不是視訊播放器,更不是看毛片,它其實是由**Knuth、Morris、Pratt**這三個大牛名字的合稱。老外很喜歡用人名來