對於KMP演算法的理解

2021-06-26 05:10:47 字數 1722 閱讀 3255

資料結構課,講至kmp演算法,由於是下午,昏昏欲睡,故,聽得如雲如霧,煙水迷濛。咀嚼書本,思路似乎捋直,卻又不甚清晰,於是細細寫下此文,欲以自明。

先來看一下bf

演算法的匹配過程:

從上圖不難看出,bf就是「窮舉」。窮舉固然沒有錯漏,但論及效率,實在不是我們的首選演算法。

那麼kmp呢?他對bf演算法的改進在什麼地方?讓我們看一下kmp演算法的匹配過程:

注意,綠色的部分是程式未進行比較的,即程式並沒有在上面花費時間。那麼,kmp演算法的優越性體現在何處呢?我們看一下程式所要花費時間的步驟:圖中藍色與紅色的部分。則,bf為6,kmp為6。效率不是一樣的嗎?別忘了,kmp可比bf多比較了乙個字元啊。

這種差別從何產生?這就基於對模式串(pattern)的研究了。現在假設程式完全了解模式串(pattern),知道p[0] == p[1] != p[2],那麼,kmp演算法就是讓程式充分利用前次比較的結果,來避免進行「不必要」的匹配。

從第一次匹配,程式知道,p[0] == t[0],p[1] == t[1],那在第二次匹配時,程式就完全沒有必要比較再去匹配p[0]與t[1]了,它們肯定相等,直接匹配p[1]與t[2]即可。同理,到了第三步,既然p[1] != t[2],那麼p[0]肯定也不等於t[2],不用匹配,p[0]直接越過t[2],與t[3]進行匹配了。

問題來了,怎樣才能對模式串(pattern)有足夠的了解呢?程式又如何知道模式串(pattern)中誰與誰相等,之後又該怎樣進行操作呢?

所謂對模式串(pattern)的了解,就是讓程式知道,p[j]與t[i]的匹配中,j與i是什麼值。觀察程式對目標串(target)中字元的操作:t[0]、t[1]、t[2]、t[2]、t[3]、t[4]...而模式串(pattern)呢:p[0]、p[1]、p[2]、p[1]、p[0]、p[1]...

其中t陣列是我們能夠想到如何操作的,而p陣列呢……那是什麼?也就是說,j的值是我們目前無法求出的。我們且將他放入乙個名為next的陣列中,假設next陣列中已經將下個j的值計算好了,那我們應該如何編寫**?

int search(string &pattern, string &target)

else

k = next[k];

return *next;

}

如此,kmp演算法就算大致完成。那麼,k = next[k]後的「有待改進」是怎麼回事?

原來,當p[j] != t[i]時,如果p[j] == p[k],那麼p[k]當然也與t[i]不匹配,就該p[next[k]]去與t[i]匹配了。

這樣,改進後的**就是:

int* getnext(string &pattern)

else

k = next[k];

return *next;

}

若目標串(target)的長度為m,模式串(pattern)長度為n,那麼,kmp演算法最壞情況的時間複雜度為o(m + n),而bf演算法最壞情況的時間複雜度為o(m * n)。

理解至此處,欣然。記下此篇,來時繼續品味。

KMP演算法的理解

串的模式匹配演算法主要有兩種,一是簡單模式匹配,而是kmp演算法。簡單模式匹配演算法很容易理解,每一次從主串的第乙個位置起和模式串的第乙個字元開始比較,如果相等就按照順序一直比下去,如果不相等就把模式串和第二個位置開始繼續進行比較,最後若匹配成功則返回主串中與模式串匹配的第乙個字元的位置,雖然簡單易...

理解KMP演算法

由暴力匹配引入kmp演算法 問題 有乙個文字串s,和乙個模式串p,現在要查詢p在s中的位置。如果用暴力匹配的思路,並假設現在文字串s匹配到 i 位置,模式串p匹配到 j 位置,則有 示例 上面s,下面p 比如從a這裡開始匹配上了 一直這樣匹配下去 到這裡匹配不上了 就回滾回去重新開始 這種回滾的問題...

對KMP演算法的理解

kmp演算法是一種高效的模式匹配演算法,複雜度可以達到o m n 而普通模式匹配演算法的複雜度為o m n 普通模式匹配演算法 從主串的第乙個字元 或者給定的第pos個字元 開始和子串的第乙個字元開始比較,若相等,則繼續比較後面的字元。若不相等,則從主串本次開始比較的字元的下乙個字元開始,與子串的第...