字串KMP匹配演算法詳解

2021-08-07 16:07:36 字數 2387 閱讀 1457

下面我再來舉個具體例子,並給出一具體執行程式:

對於目的字串big是banananobano,要匹配的字串small是nano,的情況,

下面是匹配過程,原理很簡單,只要先和big字串的第乙個字元比較,如果相同就比較下乙個字元(他們的第二個字元),如果不同就把small整體右移乙個,之後再從small的第乙個字元開始比較,如此重複進行,直到 匹配到 big 結束。這個演算法的執行過程如下圖。

}if(small_index == small_len) //說明剛好匹配(並不是差乙個)

return big_index - small_len;

else

return -1;

}int main()

我們主要把時間浪費在什麼地方呢,

此時如果向右移動一位,那麼nan最先匹配的字串行將是an,這肯定是不能匹配的,

之後再右移一位,匹配的是nan最先匹配的序列是n,這是可以匹配的。

如果我們事先知道pattern本身的這些資訊就不用每次匹配失敗後都把target_index回退回去,

這種回退就浪費了很多不必要的時間,如果能事先計算出pattern本身的這些性質,

那麼就可以在失配時直接把pattern移動到下乙個可能的位置,

把其中根本不可能匹配的過程省略掉,

如上表所示我們在index=2時失配,此時就可以直接把pattern移動到index=4的狀態,

kmp演算法就是從此出發。

舉例來說,有乙個字串"bbc abcdab abcdabcdabde",我想知道,裡面是否包含另乙個字串"abcdabd"?

首先,字串"bbc abcdab abcdabcdabde"的第乙個字元與搜尋詞"abcdabd"的第乙個字元,進行比較。因為b與a不匹配,所以搜尋詞後移一位。

因為b與a不匹配,搜尋詞再往後移。

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

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

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

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

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

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

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

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

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

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

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

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

"部分匹配值"就是"字首"和"字尾"的最長的共有元素的長度。以"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。

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

正在攻關,待續中+++

字串匹配演算法 KMP詳解

這兩天在看字串匹配演算法,第一次看到kmp演算法的時候覺得很難。於是上網搜分析,網上講kmp的演算法很多,只是好像很多都講的雲裡霧裡的,不甚清晰。後來想想還是找教材看看,第一回看的是 演算法 第四版,其實沒看懂 於是再找來clrs看,恍然大悟,果然還是clrs 好。本文主要是梳理一下整個思路,盡自己...

字串匹配KMP演算法詳解。

一 什麼是kmp演算法 假設現在有這樣乙個問題 有乙個文字串s,和乙個模式串p,現在要判斷s中是否有和p匹配的子串,並查詢p在s中的位置,怎麼解決呢?如果用暴力匹配的思路,並假設現在文字串s匹配到 i 位置,模式串p匹配到 j 位置,則有 如果當前字元匹配成功 即s i p j 則i j 繼續匹配下...

KMP字串匹配演算法詳解

kmp演算法利用匹配失敗後的資訊,儘量減少模式串與主串的匹配次數以達到快速匹配的目的。具體實現就是實現乙個next 函式,函式本身包含了模式串的區域性匹配資訊。時間複雜度o m n 例如 第 j 1 個字元的next函式值next j 1 等於3,意味著它的前三個字串,s j 2 s j 1 s j...