KMP演算法的個人理解

2021-09-10 19:19:17 字數 2066 閱讀 5801

kmp演算法是一種改進的字串匹配演算法,由d.e.knuth,j.h.morris和v.r.pratt同時發現,因此人們稱它為克努特——莫里斯——普拉特操作(簡稱kmp演算法)。kmp演算法的關鍵是利用匹配失敗後的資訊,儘量減少模式串與主串的匹配次數以達到快速匹配的目的。

kmp演算法的核心內容是乙個部分匹配表(pmt—partial match table),pmt**的數值就是匹配失敗後的可利用資訊,今天就著重討論kmp演算法中的幾個核心內容:1.pmt陣列的求解;2.pmt**的意義及在kmp演算法中的應用;3.next陣列的應用。

以圖1.1為例,我們將目標字串定義為p,需要查詢的字串定義為s,字串匹配即找到s在p中的位置,並返回起始字串的下標。

圖1.1 字串匹配

在匹配的過程中,當i和j指標所指向的字串不匹配時,即出現圖1.2所示的情況,此時,kmp演算法和普通匹配演算法的差別就顯現了出來。

圖1.2 kmp中指標j回退

我們發現,在匹配的過程中,由於字串p在i指標之前的字元「ab」與字串s的初始字元「ab」相同,為了演算法的簡單化,略過"ab"字元從第三位字元開始匹配。那麼問題的核心內容來了,我們怎麼知道應該略過哪些字元?

根據圖1.2所示的內容我們很容易可以得出結論,在字串p中i之前的k個字元字串s中第0位之後的k個字元完全相同的情況下,就可以略過這k個字元。可是這樣比較仍舊比較麻煩,我們還可以對其簡化,由於匹配到i和j之後,出現不匹配現象,那麼在字串p中i之前的j-1個字元一定是與字串s的前j-1個字元相同,這是匹配過程給我們的有效資訊。那麼我們把所有的字串操作放在字串s中,就可以引入乙個概念,字串的字首字串和字尾字串

以字串「abab」為例,字首字串分別為「a」,"ab","aba",,字尾字串分別為「b」,「ab」,"bab"。其中字首字串和字尾字串中最大的相同字串為「ab」,大小為2。這個大小值即為上一段中提到的k,在示例字串中前2位的字串和後2位的字串完全相同。

回到字串s和字串p,我們發現當i指標值為4時,出現不匹配現象,在計算略過字串時,正好是我們上一段中所討論的「abab」字串,計算結果為k=2,略過「ab」字串。

總結一下上述內容,我們可以發現,如果知道字串中每個字元的字首字串和字尾字串的最大相同字串數值,在回退j指標時,只需要回退對應的數值即可,本著這樣的目的,我們由此退出了pmt陣列,以「ababd」為例,如圖1.3所示。

圖1.3 pmt陣列和next陣列

在圖1.3**現了乙個next陣列,我們發現next陣列除了第0位字串為-1,其餘數值為pmt陣列的右移一位的結果。為什麼要構建這麼乙個next陣列呢,因為我們發現,當指標指向j時出現不匹配現象,實際上我們需要查詢的卻是j-1位的pmt值,如果pmt陣列整體右移一位,我們可以直接查詢j位的next陣列值,從而直接知道我們的j指標應該回退到的位置

最後附上c++的kmp演算法**,可以拿去測試和理解。拋磚引玉之作,希望與各位交流討論。

#include #include using namespace std;

void getnext(char *s, int *next)

else

}}int kmp(char *p,char *s,int *next)

else

}if (j == strlen(s))

return i - j;

else

return -6;

}void main()

KMP 演算法(個人理解)

相信大家看了 matrix67 的講解,一定已經知道了 kmp 演算法是怎麼回事,怎麼操作的,為什麼時間複雜度不高 這裡,我主要是分享我對 kmp 的理解 kmp 的精髓是什麼?這個東西,各自有個字的理解,很多人都覺得是避免了重複匹配,而我的理解是預處理 為什麼是預處理?你看看 kmp 的執行過程 ...

KMP演算法的個人理解

自學了一段時間,剛剛準備轉行做軟體開發,面試過程中被指出計算機基礎知識薄弱。因為是非科班出生,確實有些計算機方面的基礎沒有學過,也開始惡補這些方面的東西。最近在學習資料結構與演算法過程中,學到kmp演算法,甚是難解。看了阮一峰的網路日誌後才慢慢理解,但也發現其中的瑕疵,在此也順帶指出,至於對或不對,...

個人理解的kmp演算法

kmp還是挺難上手的,看書加看部落格,看了有五六篇才理解,看了大概四個小時。include include include using namespace std next陣列本質是模式串中的字首和字尾的相等數 int next 555 得到next陣列的過程也是模式串自身匹配的過程 void ge...