KMP算法的学习经验
KMP算法的學習經驗
(歡迎指正錯誤, 歡迎噴)
一.什么是kmp
KMP算法是一種改進的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同時發現,因此人們稱它為克努特——莫里斯——普拉特操作(簡稱KMP算法)。KMP算法的關鍵是利用匹配失敗后的信息,盡量減少模式串與主串的匹配次數以達到快速匹配的目的。具體實現就是實現一個next()函數,函數本身包含了模式串的局部匹配信息。時間復雜度O(m+n)。
————來自百度百科
簡單的說 :
1.kmp是一種字符串匹配算法。
2.它的優點就是能通過 next[]數組(一個記憶數組),減少匹配的次數, 從而節省時間。
3.關鍵是next[] 這個記憶數組。
二.kmp的額外知識
由D.E.Knuth,J.H.Morris和V.R.Pratt同時發現,因此人們稱它為克努特——莫里斯——普拉特操作(簡稱KMP算法)
并且kmp被很多人叫做,看(k)毛(m)片(p)算法。
三.普通暴力匹配
//ptr[] 匹配串, str[] 主串
1.暴力匹配
我們的普通暴力匹配是 匹配串ptr 的字符一個一個和 主串匹配。
如果一個字符匹配成功:ptr的下一個字符繼續匹配,
如果失敗 :str[]回溯到開始匹配的位置(i = i - j, <-下面有講解),然后再以 下一個位置為開始, 再次重新進行字符串匹配。
暴力匹配代碼:
int plen = strlen(ptr);//匹配串的長度 int slen = strlen(str);//主串的長度 int i, j = 0; //i 和j 分別代表 當前 str 和ptr 所匹配的字符下標 int flag = 0;//如果為 1 表示 主串中存在 匹配串。 for(i = 0;i < slen;i++) {if(str[i] == ptr[j])//如果匹配成果 繼續下一個匹配{j++;}else//如果 不相等 {i = i- j;//主串回溯, i回到匹配前的位置j = 0;//匹配串 要從頭開始}if(j == plen)// 主串中存在客串 匹配串成功{flag = 1;break;//結束} }以上是暴力匹配 的代碼, 這也能解決字符串匹配的問題(這種方法沒有一點錯誤), 然而你用這種方法去解題,很多題只能送你個:
acmer的你,看到這就是很尷尬了。
為什么呢?
因為你暴力匹配太盲目了, 而kmp確實聰明的 kmp的j知道往哪跳。
四. 相同前后綴的講解:
1.什么是前后綴。
如:ABCD這個字符串
A
AB
ABC
就是他的前綴。
BCD
_CD
__ D
就是它的后綴。
·下劃線只是營造效果, 沒有意義。
2.相同前后綴:
如:ABCAB這個字符串
AB(前綴) AB(后綴) 就是相似前后綴(而且AB是最長的相似前后綴)。
五.kmp的next數組
kmp 通過next數組, 保留了ptr(匹配串)以每個字符結尾的子串的 最長相同前后綴的長度。通過next 主串就不用回溯, 只需ptr(匹配串)來回的跳(有想法的跳 o(* ̄︶ ̄ *)o)就行。
{
如:1. 主串ABCABCABD 客串ABCABD
2.當匹配到:
ABCABCABD
ABCABD 與其失配。
但是我們已經匹配了ABCABCABD 這個AB 我們已經知道他匹配,
所以根據ptr的 前后綴相似的性質(ABCABD), 直接跳到相似前綴的哪里 接著往后匹配。
所以就要知道next數組怎么獲得。
}
那么接下來就看個有圖的栗子(例子): 主串:ABABAC 匹配串: ABAC /***next數組的獲取*/ int Get_next() {int plen = strlen(ptr);next[0] = -1;int k = -1;//表示上一次匹配的最長前后綴長度for(i = 0; i < plen; i++){if(k == -1 || ptr[i] == ptr[k])// ptr[i]是后綴的對后一個字符, ptr[k]是前綴的最后一個字符。 k = -1是以第一個字符結尾的子字符串沒有前后綴,因此就要有個操作, 解決 第一個字符串就匹配失敗的情況。{k++;//如果本次匹配成功 , 長度加一next[i+1] = k;//數組儲存}else//不成功{i--;//主串不動k = next[k];//長度縮減再次匹配, 對于k為什么等于next[k] ,后續會有講解。}} } /***kmp 匹配過程****/ int kmp(char str[], char ptr[]) {int flag = 0; // flag = 1 表示 主串中含有 匹配串int slen = strlen(str);int plen = strlen(ptr);int i, j = 0;for(i = 0;i < slen;i++){if(j == -1||str[i] == ptr[j])//j == -1是:當第一個字符串就不匹配時, 整個匹配串要整體往右移一個。{j++;}else {i--;j = next[j];//匹配失敗 j 跳到一上一個字母結尾的前綴后面+1處,}if(j == plen){flag = 1;break;}}return flag; }六. k = next[k]的理解:
其他大佬對k = next的理解入口->
本人的講解:
當匹配失敗時 主串 i會停留不動,
k 會都等于 next[k]。
一下圖片是 AAACAAAA和它next[]數組情況正確
接下來是過程
深入了解kmp 請看大牛的講解->
轉載于:https://www.cnblogs.com/TJack/p/10526956.html
總結
以上是生活随笔為你收集整理的KMP算法的学习经验的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Generative Adversari
- 下一篇: jupyter安装出现问题:安装后无法打