kmp演算法是一種優秀的字串匹配演算法,字串匹配的常規演算法是一步一步進行移位和比較操作,直至找到完全相匹配的字串。
下面通過乙個例子,為大家仔細說明kmp演算法的使用和思路:
問題:在字串「deabcdababcdabcdabde」字串中,匹配字串"abcdabd".
演算法思路:
kmp演算法的思路在於,根據已經匹配的部分字元的資訊,不把搜尋位置移回已經比較過的位置,這樣就提高了效率,是不是還是有點不清楚?沒關係,讓我們來根據乙個例子來切實體會一下kmp演算法是如何實現的。
**:1、kmp演算法的核心是一張「部分匹配表」,這個表是怎麼來的,後面再說,先用了再說,下圖就是該問題的部分匹配表。
這個表上面一行是我們的模式字串,下面一行是每個字元所對應的匹配值
移位規則是 移動位數 = 已匹配的字串長度 - 已匹配字串的最後一位字元所對應的匹配值。
2、接下來就開始進行操作
上圖中我們看到,移位兩位後,我們找到了部分匹配的字串"abcdab",但並沒有找到完全匹配的字串,如果是常規思路,就是在繼續往下一步一步移位,但我們這裡不這樣進行,我們觀察到,已經匹配的字串長度是6,匹配到的最後乙個字元是"b",查詢部分匹配表,這個「b」的部分匹配值是2,那麼根據我們演算法的移位規則,下一步我們的移位長度 = 6 - 2 = 4;
╮(╯▽╰)╭,有沒有發現,移了4位之後,剛好到達了下乙個「ab」處?是不是很神奇?好了,打住,我們繼續往下移,當前已匹配的字串長度為2,查詢這個「b」的匹配值為0(別和上個b搞混了),根據演算法,我們接下來移位長度是 2 - 0 = 2;
繼續,和前面的步驟相同,我們這次移位長度為 6 - 2 = 4;
至此,我們已經找到了完全匹配的字串,當然,如果母字串的長度較長,我們可以繼續進行移位,繼續尋找,和之前的步驟相同,下次我們移位長度為 7 - 0 = 7。
演算法分析:
不知道大家看到現在,有沒有一點明悟?來,讓我們分析一下模式字串「abcdabd」:
對於搜尋來說,我們首先關注的肯定是第乙個字元,如果第乙個字元都不匹配,那麼後面的字元就沒有比較的必要了,該目標字串的第乙個字元是』a『,讓我們看看這個字串裡有沒有』a『,誒,還真有,假如說我們現在已經匹配了「abcda」,5個字元,我們要移4位才能從第乙個'a'移到第二個'a',』a『只有乙個字元,5 - 1 = 4;
再往下看,關注完第乙個字元,我們開始關注和第乙個字元依次相連的子字串,這些字串有乙個共性,就是第乙個字元都是』a『,那我們看看這種字串能有多少,"ab","abc","abcd","abcda","abcdab","abcdabd",再看看這些字串在目標字串「abcdabd」中存在幾個,可以看出,除去和第乙個「a」相連的,「ab」還有乙個,其餘的沒有,而"ab"長度為2,所以在表中,第二個b的匹配值為2。
該演算法的核心思路在於,有時候,字串的頭部和尾部可能會有重複。
不知道大家有沒有聽懂?讓我們把匹配字串換一下,換成「abcdabc」,現在的部分匹配表應該是:
演算法思考和延伸:
如果模式字串過長,部分匹配表的生成會占用較多的時間,如何去提高部分匹配表的生成效率,是該演算法的優化所在。(個人觀點,如有大佬,請指教!)
該演算法思想和字典編碼有一定的相通之處。改天我會寫出乙個字典編碼的文章。敬請期待!
KMP 演算法詳解(c語言描述)
自大牛matrix67的部落格 a56b b47a a57a a37a a17a 0終於,a 8 b 1 i變為8,j為1。事實上,有可能j到了0仍然不能滿足a i 1 b j 1 比如a 8 d 時 因此,準確的說法是,當j 0了時,我們增加i值但忽略j直到出現a i b 1 為止。這個過程的 很...
資料結構 通俗語言描述KMP演算法核心
樸素的求母串s裡有多少個子串t,就是母串裡從1開始到末尾,擷取和子串相同長度的一段字串,和子串t比,一樣就返回1不一樣就繼續取下一串。要是子串裡的字元都是不一樣的就是這麼比的,但是子串裡要是有一些是重複的,這樣比就多比了很多步。next陣列就是,把子串裡各個字元位置的下標值定義為乙個陣列,告訴你這個...
演算法 KMP演算法
kmp演算法主要解決的問題就是在字串 主串 中的模式 pattern 定位問題。記主串為t,模式串為p,則kmp演算法就是返回p在t 現的具體位置,如果沒有出現則返回 1。如果 i 指標指向的字元和 j 指標指向的字元不一致,那麼把 i 右移1位,j 從0位開始,從新開始匹配 如果 i 指標指向的字...