這似乎是三個人提出來的一種演算法,然後把三個人的名字合併在一起形成了kmp這個名字(真是詭異)。這個演算法的本質是用來快速地匹配兩個字串。
現在我們有兩個字串
s=abcabcabd
t= abcabd
求出字串t是否是字串s的乙個子串(連續)。
我們顯然可以分別列舉s匹配的起始位置,然後直接判斷是否可以匹配即可。
時間複雜度o(
|s|∗
|t|)
o (|
s|∗|
t|
)我們可以發現在失配的時候,我們浪費了很多的時間來重新列舉,而kmp則是把這些浪費的時間全都去掉。
還是之前的兩個字串,我們匹配到第6個字元的時候發現失配了。
abcabcabd
abcabd
t串這個時候就要後移了。我們就可以用貪心的思想:t串肯定是移得越少越好嘛。
所以,我們可以定義乙個next陣列,next[i]表示的是:當前位置如果和第i個位置匹配,則當我們把next[i]移到到這個位置時,當前位置及前面依然是匹配的,而next[i]是整個合法方案中小於i的最大值。
所以當我們在當前位置與第i個位置失配的時候,我們就可以後移t使得next[i-1]移到當前位置的前面,接著再判斷是否可以匹配,如果不行再繼續,直到當前i-1沒有next為止。
這樣既保證了我們不會選擇無用的東西,也保證了我們不會漏選有用的東西。
依然是這兩個字串,發現next[5]是2,於是我們後移
.abcabcabd
……abcabd (可能有點醜)
我們發現可以匹配了,我們就繼續匹配到末尾為止。
j=0;
for(int i=1;i
<=n;i++)
}
此處**是匹配多次,其中j=p[j]是每一次匹配成功後為了能夠繼續匹配需要將t串後移。
其中的p代表的就是next
現在的關鍵就是,我們怎麼求next?
接著我們就可以神奇地發現,求next其實就是字串與自己本身匹配(感受一下)。
然後,你是不是已經知道怎麼做了呢?
p[0]=p[1]=0;
int j=0;
for(int i=2;i
<=m;i++)
這個演算法是個二重迴圈,總覺得怎麼都不像o(
|s|+
|t|)
o (|
s|+|
t|)。
我們來證明一下:
對於j(**中的),每一次進入while,它都會至少減1,當它=0時,就會退出
而我們知道,j最多隻會加|s|或|t|次1,因為成功匹配次數不會大於字串長度。
所以,進入while迴圈的次數最多隻會是|s|或|t|次。
時間複雜度就是線性的。
到**都可以找到吧
KMP串匹配演算法
串的模式匹配是串處理系統中的最重要操作之一,普通匹配演算法的時間複雜度為o m n 然而,kmp演算法的演算法時間複雜度為o m n 其主要改進是 當出現比較不等時,不需回溯指標,而是利用已經得到的部分匹配的結果將模式向後滑動盡可能遠的距離。kmp演算法的本質是基於有限自動機理論,它簡化了有限自動機...
模式串匹配 KMP
樸素的的模式串匹配演算法通常要在向前移動文字指標之後,回溯模式串指標,其效率為o m n 而kmp演算法則挖掘了一些模式串中的一些資訊,來加快匹配的效率。kmp演算法的緊隨便是覆蓋函式next。當模式串p j 和文字串s i 失配時,j指標不是簡單的回溯,而是指向next j 覆蓋函式next如何定...
模式串匹配,kmp
include include include include define maxstrlen 255 可以在255以內定義最大串長 typedef char sstring maxstrlen 1 0號單元存放串的長度 void get next sstring t,int next void ...