模式匹配的kmp演算法詳解
這種由d.e.knuth,j.h.morris和v.r.pratt同時發現的改進的模式匹配演算法簡稱為kmp演算法。大概學過資訊學的都知道,是個比較難理解的演算法,今天特把它搞個徹徹底底明明白白。
注意到這是乙個改進的演算法,所以有必要把原來的模式匹配演算法拿出來,其實理解的關鍵就在這裡,一般的匹配演算法:
int index(string s,string t,int pos)//參考《資料結構》中的程式
else//**************(1)
} if(j>t.length) return i-t.length;//匹配成功
else return 0;
}匹配的過程非常清晰,關鍵是當『失配』的時候程式是如何處理的?回溯,沒錯,注意到(1)句,為什麼要回溯,看下面的例子:
s:aaaaabababcaaa t:ababc
aaaaabababcaaa
ababc.(.表示前乙個已經失配)
回溯的結果就是
aaaaabababcaaa
a.(babc)
如果不回溯就是
aaaaabababcaaa
aba.bc
這樣就漏了乙個可能匹配成功的情況
aaaaabababcaaa
ababc
為什麼會發生這樣的情況?這是由t串本身的性質決定的,是因為t串本身有前後'部分匹配'的性質。如果t為abcdef這樣的,大沒有回溯的必要。
改進的地方也就是這裡,我們從t串本身出發,事先就找準了t自身前後部分匹配的位置,那就可以改進演算法。
如果不用回溯,那t串下乙個位置從**開始呢?
還是上面那個例子,t為ababc,如果c失配,那就可以往前移到aba最後乙個a的位置,像這樣:
...ababd...
ababc
->ababc
這樣i不用回溯,j跳到前2個位置,繼續匹配的過程,這就是kmp演算法所在。這個當t[j]失配後,j應該往前跳的值就是j的next值,它是由t串本身固有決定的,與s串無關。
《資料結構》上給了next值的定義:
0 如果j=1
next[j]= //注意到這裡的j==0,和++j的作用就知道為什麼規定next[1]=0的好處了
else j=next[j];//i不變(不回溯),j跳動
} if(j>t.length) return i-t.length;//匹配成功
else return 0;
}ok,是不是非常簡單?還有更簡單的,求next值,這也是整個演算法成功的關鍵,從next值的定義來求太恐怖了,怎麼求?前面說過了,next值表達的就是t串的自身部分匹配的性質,那麼,我只要將t串和t串自身來一次匹配就可以求出來了,這裡的匹配過程不是從頭乙個乙個匹配,而是從t[1]和t[2]開始匹配,給出演算法如下:
void get_next(string t,int &next)
else j=next[j]; } }
看這個函式是不是非常像kmp匹配的函式,沒錯,它就是這麼幹的!注意到(2)語句邏輯覆蓋的時候是t[i]==t[j]以及i前面的、j前面的都匹配的情況下,於是先自增,然後記下來next[i]=j,這樣每當i有自增就會求得乙個next[i],而j一定會小於等於i,於是對於已經求出來的next,可以繼續求後面的next,而next[1]=0是已知,所以整個就這樣遞推的求出來了,方法非常巧妙。
這樣的改進已經是很不錯了,但演算法還可以改進,注意到下面的匹配情況:
...aaac...
aaaa.
t串中的'a'和s串中的'c'失配,而'a'的next值指的還是'a',那同樣的比較還是會失配,而這樣的比較是多餘的,如果我事先知道,當t[i]==t[j],那next[i]就設為next[j],在求next值的時候就已經比較了,這樣就可以去掉這樣的多餘的比較。於是稍加改進得到:
void get_nextval(string t,int &next)
else j=next[j]; } }
匹配演算法不變。
到此就完全弄清楚了,以前老覺得kmp演算法好神秘,真不是人想出來的,其實不然,它只不過是對原有的演算法進行了改進。可見基礎的經典的東西還是很重要,你有本事『廢』了經典,就創造了進步
KMP演算法詳解
kmp演算法即knuth morris pratt演算法,是模式匹配的一種改進演算法,因為是名字中三人同時發現的,所以稱為kmp演算法。因為偶然接觸到有關kmp的問題,所以上網查了一下next陣列和 nextval陣列的求法,卻沒有找到,只有在csdn的資料檔案裡找到了next陣列的簡單求法 根據書...
KMP演算法詳解
相信很多人 包括自己 初識kmp演算法的時候始終是丈二和尚摸不著頭腦,要麼完全不知所云,要麼看不懂書上的解釋,要麼自己覺得好像心裡了解kmp演算法的意思,卻說不出個究竟,所謂知其然不知其所以然是也。經過七八個小時地仔細研究,終於感覺自己能說出其所以然了,又覺得資料結構書上寫得過於簡潔,不易於初學者接...
KMP演算法詳解
在介紹kmp演算法之前,先介紹一下bf演算法。一.bf演算法 bf演算法是普通的模式匹配演算法,bf演算法的思想就是將目標串s的第乙個字元與模式串p的第乙個字元進行匹配,若相等,則繼續比較s的第二個字元和p的第二個字元 若不相等,則比較s的第二個字元和p的第乙個字元,依次比較下去,直到得出最後的匹配...