離開學校已經多年了,早已經不再撫弄那些陳舊的書籍。
週末,深圳的天氣陰沉,老天這段時間總是很樂意顯擺,動不動就給深圳人民來次幾十年一遇的暴雨,似乎要把一年的雨水全部在這些天下完似的。
所以呆在家裡面看電視,上網,實在也無聊。隨手翻開大學時候的(資料結構,還留著啊,當初剛出來的時候總沒有底氣,總希望能夠隨時充電用)。看到了字串的模式匹配一章。突然發現kmp演算法是如此的經典。故記之。。。
在提kmp的經典之前,首先要提基本的模式匹配演算法:
所謂模式匹配,簡單點說就是對兩字串進行匹配,找出乙個字串在另乙個字串中的位置。
基本的模式匹配是這樣的:
假設有字串
s=s1s2......sn(由於為了演算法效率的需要,所以一般都把s[0]儲存s的長度)
p=p1p2......pm(同上)
其中(m
所以演算法要點如下:
假設從s中i點開始掃瞄(也就是從s[i]開始,此時用乙個變數k=i),順序比較s[i]和p[1],s[i+1]和p[2]。這樣,當p進行到第j個字元也就是p[j]的時候,發現s[i+j-1]和p[j]不匹配,那麼需要把s的指標i回朔到s起始的下乙個字元也就是k+1繼續比較。
如圖:
以上就是模式匹配的基本演算法,這種演算法對於大多數的匹配來說基本是o(n+m)的時間複雜度。
但是對於如下的字串:
s=0000000000000000000000000000001
p=000001
這種字串來說,每次匹配失敗都是在p到最後乙個字元也就是j=m的時候,此時s的指標又必須回朔,導致大量的匹配。此時的時間複雜度是o(n*m)。
所以基本演算法的時間複雜度是o(n*m)。當然了,對於大多數的匹配是不會有這麼高的時間複雜度的,所以這種演算法現在也在廣泛使用,因為簡單。
為了解決上述的問題,kmp演算法被發現。
kmp演算法的思想如下。匹配過程中,出現不匹配時,s的指標不進行回朔(原地不動),將p盡可能地向後移動一定的距離,再進行匹配。
如圖:
從上圖中我們看到,當s移動到i,p到j的時候失配。這時候i不回朔,而只是將p向前移動盡可能的距離,繼續比較。
假設,p向右移動一定距離後,第k個字元p[k]和s[i]進行比較。
此時如上圖,當p[j]和s[i]失配後,i不動,將p前移到k,讓p[k]和s[i]繼續匹配。現在的關鍵是k的值是多少?
通過上圖,我們發現,因為黃色部分表示已經匹配了的結果(因為是到了s[i]和p[j]的時候才失配,所以si-j+1si-j+2…si-1 = p1p2…pj-1,見黃色的部分)。所以有:
1、 si-k+1si-k+2…si-1 = pj-k+1pj-k+2…pj-1。
所以當p前移到k時,有:
2、 si-k+1si-k+2…si-1 = p1p2…pk-1。
通過1,2有
pj-k+1pj-k+2…pj-1 = p1p2…pk-1。
呵呵,此時我們的任務就是求這個k值了。。。
理解了這一點之後,終於能夠發現此演算法的經典了。
記錄KMP演算法,記錄其經典之處。。。
離開學校已經多年了,早已經不再撫弄那些陳舊的書籍。週末,深圳的天氣陰沉,老天這段時間總是很樂意顯擺,動不動就給深圳人民來次幾十年一遇的暴雨,似乎要把一年的雨水全部在這些天下完似的。所以呆在家裡面看電視,上網,實在也無聊。隨手翻開大學時候的 資料結構,還留著啊,當初剛出來的時候總沒有底氣,總希望能夠隨...
KMP演算法(2) 其細微之處
系列文章目錄 kmp 演算法 1 如何理解 kmp kmp演算法 2 其細微之處 本篇來談一談kmp的一些細微之處,直接進入主題。p為模式串,下標從0開始 void getnext string p,int next else j next j 在s中找到p第一次出現的位置 int kmp stri...
KMP演算法記錄
kmp演算法這篇寫的很好,非常好理解 這個演算法用來做字串匹配。字串匹配是計算機的基本任務之一。如果給出兩個字串text 和 pattern 需要判斷字串pattern 是否為字串text 的子串。一般把字串text 稱為文字串,而把字串pattern 稱為模式串。舉例來說,有乙個字串 bbc ab...