資料結構 串的模式匹配 KMP演算法

2021-10-25 11:36:33 字數 2331 閱讀 7168

目錄概念

簡述kmp演算法原理 **

計算next陣列

kmp演算法 測試

改進kmp演算法簡介

從s中匹配t串,在bf演算法中,通過指標回溯不斷進行匹配,其思想是窮舉。效率很低,但有些串有一定的規律,不需要回溯s串的指標,這就是kmp演算法。

比如 s: aaaaaab

t:  aaab

在進行比較時,如果按照bf演算法,需要進行最後一次才能匹配成功。但是我們發現s和t串前幾位是相同的,不需要重複比較。當然,計算機不會像人這麼敏感,但是能否設計出一種演算法,提高類似這種模式匹配的效率呢?答案是肯定的,這就是kmp演算法。

kmp演算法是由三個外國人k某、m某、p某三人提出的,所以叫kmp演算法。

kmp演算法的核心是針對模式串下手,提取器規律來用於加速匹配過程。

比如,上述匹配過程中s[3]≠t[3],如果按照bf演算法,t指標回溯到t[0],s指標回溯到s[1],繼續進行匹配,s[1]=t[0],s[2]=t[1],這兩個都匹配成功了。嗯,但這個過程有沒有必要呢?

答案是否定的,確實沒必要!

為什麼?

原因在t串身上

觀察t串可以發現第一次沒有匹配成功的t[3]前面的兩個元素和t串開頭的兩個元素相同,t[0]~t[1]=t[1]~t[2]。而既然我們第一次匹配進行到t[3]了,說明前面的都匹配成功了,即有s[1]=t[1],s[2]=t[2]

這樣一來,就由上兩個(綠色)式子得到s[1]=t[0],s[2]=t[1]。也就是說,我們根據前面的條件就已經可以推出s[1]=t[0],s[2]=t[1],而不需要將s進行指標回溯再重新匹配了,只需要將t指標回溯到t[2]即可,再進行t[2]和s[3]的比較...

這裡匹配到s和t不需要像bf演算法那樣回溯的核心是什麼?t的t[0]~t[1]=t[1]~t[2]的這個規律,它是s[1]=t[0],s[2]=t[1]的必要條件。也就是說:如果模式串的任意乙個字元的前面的k個字元與開頭k個字元相同,那麼當匹配到該字元不成功時就不需要t指標完全回溯,只需要直接用k作為新的要匹配元素的下標就行。

我們建立乙個陣列next,先掃瞄t串來記錄t串對應位置的k值,後續匹配過程中遇到匹配失敗的時候t串需要回溯到的值k,直接查next表就可以。

這裡用到的一些定義在這篇文章的**裡有。

void gerenext(sqstring t,int *next)

else

k = next[k];//這裡為什麼不是k=-1呢?因為k=-1和k=next[k]是一樣的。

}}

j從頭不停地掃到尾,k則在頭部掃瞄頭部與j匹配的元素個數。本質上其實這也是乙個匹配過程,可以把j掃瞄的當作s串,把k掃瞄的部分當作t串,這也是為什麼k = next[k];而不是直接讓k=-1。

該函式本質上是開頭k個元素組成的串與整個串的模式匹配的過程!匹配結果就儲存在next陣列中(i元素前面k個字元和開頭k個字元匹配成功,儲存為next[i]=k)。k = next[k],本質上是乙個指標回溯,因為j不回溯,所以k不能直接回溯到-1,而是應該回溯到next[k]。這個函式本身就是計算next陣列的,但在計算這個陣列的過程中又用到了這個陣列,可以說是自給自足、自產自銷了。。。關於k=next[k]的詳細的解釋點這裡。

如上所示,這種情況下,t串會根據next陣列一直回溯一直到k=-1,但是都是相等的,因此回溯過程是沒必要的!

能不能一步回溯到位呢?

資料結構例程 串的模式匹配(KMP演算法)

本文針對資料結構基礎系列網路課程 4 串中第5課時串的模式匹配 kmp演算法 kmp演算法 include include sqstring.h void getnext sqstring t,int next 由模式串t求出next值 else k next k int kmpindex sqst...

資料結構 串的樸素模式和KMP匹配演算法

一 樸素模式 假設我們要從主串s goodgoogle 中找到子串t google 的位置,步驟如下 i表示主串的當前位置下標,j表示子串的當前位置下標,如上圖在第一輪比較 i 1開始 中j 4和i 4的位置不匹配,接下來就要指標回退,從i 2開始比較,如下 如此反覆直到比較到 i 主串長度 子串長...

資料結構 字串模式匹配的KMP演算法

kmp演算法是模式匹配的一種演算法,他的思想是,當我們進行模式匹配的時候,不用像暴力解法那樣乙個乙個字元去比較,而是從前一串字元的最大前字尾開始匹配,這樣就節省了不少時間 數學推導 假如i代表主串指標,j代表子串指標 如果有 i2 j2 j1 j2 那麼i2 j1,我們在後乙個字元失配 的時候,可以...