字串匹配的KMP演算法的初步理解

2021-10-10 07:06:18 字數 2158 閱讀 7322

字串匹配的kmp演算法的初步理解

字串的匹配的問題是指有乙個長的字串a以及乙個短的字串b

如果b與a中的一部分完全匹配,那麼得到b字串的首字元在字串

a中的位置。

尋找乙個短的字串在乙個長的字串中的匹配情況,類似於以一把

鑰匙在一堆鎖頭中找到匹配的鎖頭。鑰匙與某一把鎖頭的匹配嘗試只需要

一次,為了防止重複嘗試,可以把鎖頭排成一行,逐一嘗試。

短的模式字串b相當於鑰匙,一把鎖頭相當於長字串的一部分,排成一

行的所有鎖頭相當於長字串a,字串中的乙個字元,相當於鑰匙中的乙個齒。

在匹配的嘗試的過程中,鑰匙與鎖頭的乙個乙個齒匹配,發現不匹配,把鑰匙

移動到鎖佇列的下乙個鎖的位置。

字串匹配的傳統做法是首先用a,b的首字元對齊,從前向後匹配,如果完全匹配時,

任務結束,如果中間在a的第n個字元與 b的第m個字元不匹配時,那麼b在a中的相對位置

向後移動乙個字元的位置,再從b的第1個字元與 a的第 n-(m-2)個字元開始匹配。

在匹配開始前,字串a是未知的,字串  b是已知的,正如我們不知道鎖頭的齒的形狀,

但我們知道鑰匙的齒的形狀,通過對鎖頭佇列的一遍匹配嘗試,鎖頭的鎖齒與鑰匙的齒是否

匹配的情況,才成為已知的。

正因為a是未知的,所以a中的每個字元至少需要被掃瞄讀取一次,以確定a中的某乙個字元是否

與b中的對應字元是否是匹配的。

在傳統做法中,當a中第n個字元與b中第m個字元不匹配時,由於未利用b的已知性,來了解b

的已匹配的前m個字元的相似程度,只能讓字串b謹慎地在a中的相對位置向後移動乙個字元

考慮兩種極端情況,一是b的前m-1個字元是兩兩完全不同的,完全不相似,這時我們可以

放心大膽地把b在a中的相對位置移動m-1個字元,直接比較a的第n個字元與b的首字元。

二是b的前m-1個字元是完全相同的,這時我們只能把字串b在a中的相對位置向後移動

乙個字元,但是我們不用再從b的首字元開始匹配,而是從b的第m-1個字元與a的第n個

字元匹配。

由於上述情況對b的第m-1個字元的相似性的利用,我們驚奇地發現在兩種極端的情況下,我們

不管把b在a中的相對位置向後移動乙個位置或者是m-1個字元的位置,我們都是直接用a的

第n個字元與b的m-1或者是第乙個字元進行匹配。

從字串a的角度上看,我們都是在第n個字元不能匹配時,再一次用這個字元與b中的前m-1

個已匹配的字串中的字元進行匹配。而不是向前回溯到從b的第1個字元與 a的第 n-(m-2)個字元

開始匹配。

傳統做法的缺點是當a的第n個字串與b的第m個字元不匹配時,要進行(m-2)個的回溯。根據上述的

描述,至少是在這兩個極端的情況下,回溯性的匹配是多餘的,我們能不能在其它的情況下也不回溯呢?

對這個問題的完美的解決方案,就是kmp演算法的精妙之處,也是它的價值所在。

在絕大部分的情況下,都是b的前m-1個字元,部分程度地相似。有沒有哪種或者是哪些相似的情況

能讓我們在字串a中不必回退呢?

模擬一下鑰匙與鎖頭的匹配,鑰匙插入鎖頭匹配了m-1個齒,到鑰匙的第m個齒未匹配,為了與字串問題

更類似,我們把鎖頭設想為不同程度凹槽的鏈條,在鑰匙的第m個齒不匹配時,鑰匙在鏈條上向後滑動乙個齒,

發現鎖鏈與鑰匙未完全咬合,再向後滑動乙個齒,仍發現鎖鏈與鑰匙未完全咬合,直到向後滑動了一段距離,

若干個齒之後,比如滑動了k個齒,發現了完全咬合的狀態,這時鑰匙在鎖鏈上的齒有(m-1)-k個,此時

可以用鎖鏈第n個凹槽與鑰匙的第m-k個齒進行匹配嘗試了。在這種滑動了k個齒後,鑰匙就與鎖鏈上的凹槽

完全咬合時,鑰匙上的齒有什麼特點呢?根據觀察鑰匙的齒,不難看出,是鑰匙的尖部的m-1)-k個齒與根部

的m-1)-k個齒完全角狀相同。

把上述鎖鏈與鑰匙匹配的鑰匙特徵用字串的數學語言描述,這個條件就是

a1a2a3....a(m-1-k)=a(k+1)........a(m-3)a(m-2)a(m-1)

這樣根據鑰匙中匹配的m-1個齒中,鑰匙尖部與根部相同的齒的最大齒數k, 我們就能在鏈條 第n個凹槽與

鑰匙第m個齒不匹配時,確定乙個向後滑動的鑰匙的齒數是m-1-k.然後直接用鏈條的第n個凹槽與

鑰匙第k+1個齒做匹配測試。

綜上所述,有了如上的理解,就能看懂kmp演算法的原理,意圖與具體的實現細節了。

字串匹配的KMP演算法

舉例來說,有乙個字串 bbc abcdab abcdabcdabde 我想知道,裡面是否包含另乙個字串 abcdabd 許多演算法可以完成這個任務,knuth morris pratt演算法 簡稱kmp 是最常用的之一。它以三個發明者命名,起頭的那個k就是著名科學家donald knuth。這種演算...

字串匹配的KMP演算法

舉例來說,有乙個字串 bbc abcdab abcdabcdabde 我想知道,裡面是否包含另乙個字串 abcdabd 許多演算法可以完成這個任務,knuth morris pratt演算法 簡稱kmp 是最常用的之一。它以三個發明者命名,起頭的那個k就是著名科學家donald knuth。這種演算...

字串匹配的KMP演算法

收藏 字串匹配是計算機的基本任務之一。舉例來說,有乙個字串 bbc abcdab abcdabcdabde 我想知道,裡面是否包含另乙個字串 abcdabd 許多演算法可以完成這個任務,knuth morris pratt演算法 簡稱kmp 是最常用的之一。它以三個發明者命名,起頭的那個k就是著名科...