KMP演算法(2) 其細微之處

2021-08-01 02:23:12 字數 1394 閱讀 8006

系列文章目錄

kmp 演算法(1):如何理解 kmp

kmp演算法(2):其細微之處

本篇來談一談kmp的一些細微之處,直接進入主題。

/* p為模式串,下標從0開始 */

void getnext(string p, int next)

else

j = next[j];

}}/* 在s中找到p第一次出現的位置 */

int kmp(string s, string p, int next)

else

j = next[j]; //當前字元匹配失敗,進行跳轉

}if (j == p_len) //匹配成功

return i - j;

return -1;

}

上述**的起始下標都是從0開始的,但每個人對陣列起始位置的編碼習慣不同,大致分為兩類:0和1。對於上面的**,起始位置如果改為1的話又是怎樣呢?

它們的區別之處很容易看出來,整體的**結構不變。但它們的區別並不止如此。我們知道,kmp演算法的next[i]表示相同的最長前字尾,但這對起始位置為1的next[i]卻不再適用。i0

1234

567模式串ab

cdab

d『\0』

next[ i ]-10

0001

20 i

1234

5678

模式串abc

dabd

『\0』

next[ i ]01

1112

31上面兩幅圖表展示的是:相同模式串下不同起始位置的next值對比。

相比之下,起始位置為1的next值比起始位置為0的next值多了1。多1,不是巧合,而是必然。這很容易證明。

在getnext()中,j從0開始(起始位置為1),在走了相等步後停下依次賦值給next[i],因此相較於起始位置為0的next總是多1。這又引起了我們的思考,多了1後在模式匹配中,next還會正確的實現跳轉麼?當然會了,next多1,同時模式串的起始位置也多了1,這就好比數學中,從a=b轉化為a+1=b+1,形式不同但完全等價。

先來看乙個問題,在主串s中找到模式串p所有可以完全匹配的位置。

很簡單,典型的kmp模式匹配。

假設起始位置都是從0開始,對於上圖,若已找到主串的第乙個完全匹配位置即0–4,那麼請問接下來模式串如何移動?

不知道各位讀者有沒有注意過模式串最後末尾處的next值代表什麼?(末尾即為字串的結尾標誌:』\0』)

它代表整個模式串的最長相同前字尾。

利用這個next值,我們直接可以通過next實現跳轉,更快地找到下乙個匹配點。

文章**我的個人部落格:

記錄KMP演算法,記錄其經典之處。。。

離開學校已經多年了,早已經不再撫弄那些陳舊的書籍。週末,深圳的天氣陰沉,老天這段時間總是很樂意顯擺,動不動就給深圳人民來次幾十年一遇的暴雨,似乎要把一年的雨水全部在這些天下完似的。所以呆在家裡面看電視,上網,實在也無聊。隨手翻開大學時候的 資料結構,還留著啊,當初剛出來的時候總沒有底氣,總希望能夠隨...

記錄KMP演算法,記錄其經典之處。。。

離開學校已經多年了,早已經不再撫弄那些陳舊的書籍。週末,深圳的天氣陰沉,老天這段時間總是很樂意顯擺,動不動就給深圳人民來次幾十年一遇的暴雨,似乎要把一年的雨水全部在這些天下完似的。所以呆在家裡面看電視,上網,實在也無聊。隨手翻開大學時候的 資料結構,還留著啊,當初剛出來的時候總沒有底氣,總希望能夠隨...

字串查詢 2 KMP演算法

knuth morris pratt字串查詢演算法,簡稱kmp演算法,常用於在乙個文字串s中查詢乙個模式串p出現的位置,因為這個演算法有donald knuth,vaughan pratt,james h.morris與1977年聯合發表,因此取這3個人的姓氏的命名此演算法。int kmpsearc...