KMP演算法最淺顯理解 一看就明白

2021-08-19 03:35:53 字數 2363 閱讀 1138

目錄(?)

[-]說明

kmp演算法求解什麼型別問題

演算法說明

**解析

kmp測試

複雜度分析

進一步說明2018-3-14

kmp演算法看懂了覺得特別簡單,思路很簡單,看不懂之前,查各種資料,看的稀里糊塗,即使網上最簡單的解釋,依然看的稀里糊塗。

我花了半天時間,爭取用最短的篇幅大致搞明白這玩意到底是啥。

這裡不扯概念,只講演算法過程和**理解:

字串匹配。給你兩個字串,尋找其中乙個字串是否包含另乙個字串,如果包含,返回包含的起始位置。

如下面兩個字串:

char *str = "bacbababadababacambabacaddababacasdsd";

char *ptr = "ababaca";

str有兩處包含ptr

分別在str的下標10,26處包含ptr。

問題型別很簡單,下面直接介紹演算法

一般匹配字串時,我們從目標字串str(假設長度為n)的第乙個下標選取和ptr長度(長度為m)一樣的子字串進行比較,如果一樣,就返回開始處的下標值,不一樣,選取str下乙個下標,同樣選取長度為n的字串進行比較,直到str的末尾(實際比較時,下標移動到n-m)。這樣的時間複雜度是o(n*m)。

kmp演算法:可以實現複雜度為o(m+n)

為何簡化了時間複雜度:

充分利用了目標字串ptr的性質(比如裡面部分字串的重複性,即使不存在重複字段,在比較時,實現最大的移動量)。

上面理不理解無所謂,我說的其實也沒有深刻剖析裡面的內部原因。

考察目標字串ptr:

ababaca

這裡我們要計算乙個長度為m的轉移函式next。

next陣列的含義就是乙個固定字串的最長字首和最長字尾相同的長度。

比如:abcjkdabc,那麼這個陣列的最長字首和最長字尾相同必然是abc。

cbcbc,最長字首和最長字尾相同是cbc。

abcbc,最長字首和最長字尾相同是不存在的。

**注意最長字首:是說以第乙個字元開始,但是不包含最後乙個字元。

比如aaaa相同的最長字首和最長字尾是aaa。**

對於目標字串ptr,ababaca,長度是7,所以next[0],next[1],next[2],next[3],next[4],next[5],next[6]分別計算的是

a,ab,aba,abab,ababa,ababac,ababaca的相同的最長字首和最長字尾的長度。由於a,ab,aba,abab,ababa,ababac,ababaca的相同的最長字首和最長字尾是「」,「」,「a」,「ab」,「aba」,「」,「a」,所以next陣列的值是[-1,-1,0,1,2,-1,0],這裡-1表示不存在,0表示存在長度為1,2表示存在長度為3。這是為了和**相對應。

下圖中的1,2,3,4是一樣的。1-2之間的和3-4之間的也是一樣的,我們發現a和b不一樣;之前的演算法是我把下面的字串往前移動乙個距離,重新從頭開始比較,那必然存在很多重複的比較。現在的做法是,我把下面的字串往前移動,使3和2對其,直接比較c和a是否一樣。

if (str[k + 1] == str[q])//如果相同,k++

next[q] = k;//這個是把算的k的值(就是相同的最大字首和最大字尾長)賦給next[q]}}

int kmp(char *str, int slen, char *ptr, int plen)

}return -1;

}

char *str = "bacbababadababacambabacaddababacasdsd";

char *ptr = "ababaca";

int a = kmp(str, 36, ptr, 7);

return 0;

注意如果str裡有多個匹配ptr的字串,要想求出所有的滿足要求的下標位置,在kmp演算法需要稍微修改一下。見上面注釋掉的**。

**

KMP演算法最淺顯理解 一看就明白

kmp演算法看懂了覺得特別簡單,思路很簡單,看不懂之前,查各種資料,看的稀里糊塗,即使網上最簡單的解釋,依然看的稀里糊塗。我花了半天時間,爭取用最短的篇幅大致搞明白這玩意到底是啥。這裡不扯概念,只講演算法過程和 理解 字串匹配。給你兩個字串,尋找其中乙個字串是否包含另乙個字串,如果包含,返回包含的起...

GIL對多執行緒的影響一看就明白

gil全稱global interpreter lock 全域性直譯器鎖 gil和python語言沒有任何關係,只是因為歷史原因導致在官方推薦的直譯器cpython中遺留的問題。多執行緒 每個執行緒在執行的過程中都需要先獲取gil,保證同一時刻只有乙個執行緒可以執行 但是當遇到io阻塞會自動的釋放g...

並查集 你一看就明白就會用

本文分成兩個部分,第一部分是基礎知識,這一塊這篇文章就講得非常好了,生動有趣又簡單易懂,是我見過的最好的演算法解說博文。既然它已經做到最好,我就沒必要做重複的事情了,就在這裡給大家點乙個方向。我要做的是第二部分,就是給出題型模板與刷題。我們不能光會理論,不知道怎麼應用。針對於並查集,我選的是力扣54...