那些有關求解next陣列的演算法

2021-09-08 11:29:27 字數 1754 閱讀 6138

next陣列的歷史

有關字串的模式匹配演算法中,比較容易寫出的是樸素的匹配演算法也就是一種暴力求解方式,但是由於其時間複雜度為子串長度和主串長度的乘積,例如strlen(substr) = n,strlen(mainstr) = m,則其時間複雜度為o(mn)。

為了能夠得到更有效的匹配演算法,d.e.knuth與v.r.pratt和j.h.morris同時發現,因此人們稱它為克努特--莫里斯--普拉特操作(簡稱kmp演算法)。kmp演算法的關鍵是利用匹配失敗後的資訊,儘量減少模式串與主串的匹配次數以達到快速匹配的目的。具體實現就是實現乙個next()函式,函式本身包含了模式串的區域性匹配資訊。這也即是kmp演算法的設計思想。

next陣列的求解思路

求next陣列,next[j]表示,當模式串j位置與主串i位置處發生不匹配時,i指標不回溯,j指標回溯到next[j]的位置。

對於求next[j]有三種情況:

1、j = 0時,next[j] = -1;//即模式串的第乙個字元與主串i位置發生不匹配,應將i跳過當前位置,從下乙個位置和模式串的第乙個字元繼續比較。

2、假設已知next[j] = k,即substr[0,...,k-1] = substr[j-k,j-1]。當substr[k] = substr[j]時,也就是說模式串滿足substr[0,...,k] = substr[j-k,j],可以得知next[j+1] = k + 1 = next[j] + 1;

3、當substr[k] != substr[j]時,就需要從k位置之前去查詢與substr[j]匹配的位置,假設為j'。這樣問題又可以轉化為第二種情況,即next[j+1] = next[j'] + 1 = k' + 1。

三種求解next陣列的演算法

但是如何去求解next陣列呢?有關這個問題,我思考了很長時間,下面給出幾種演算法:

演算法一,嚴格根據next陣列的定義:

1

void getnext(char substr,int

next)215

//情況三,不相等的話,要回溯j指標,substr[j'] = substr[i-1]的位置j'

16else

1726 t--;27}

28if (t < 0

)29 j = 0

;30 k =next[j];31}

3233

}34 }

演算法二,演算法的設計思想和演算法一大致相同

void getnext(const

char p, int

next)

if (p[q-1] == p[k])//

如果相等,那麼最大相同前字尾長度加1

if (k == -1

) k = 0

; next[q] =k;

}}

演算法三,更加優化的求解next陣列的演算法

void getnext(const

char substr, int

next)

//情況三,不同則j指標回溯

else

j =next[j];

}}

現在來進行總結一下,對於演算法一和演算法二來說,它們的時間複雜度是一樣的,但是相對於演算法三來說,雖然不如演算法三高效,但是比較容易理解!

ps:如果有誤的地方,請指出,共同進步!

KMP演算法Next陣列求解

相信對於kmp演算法本身大家都理解,最難理解的就是這個next陣列的求解了。這是 p 為模式串,下標從 0 開始 void getnext string p,int next else j next j 根據我的理解,i 和 j 可以看成是兩個指標,用來跟蹤當前匹配的位置。可以發現 i 是會不斷的往...

KMP演算法 next陣列的求解

void getnext vector int next,string s if s i s j next i j 為什麼j按照上述的更新方法,是s 0 i 這個字串中字首和字尾相等的最大字串的長度 j的更新方式 如果s i s j j一直回退 j next j 1 直到回退到s j s i 如果s...

KMP演算法 快速求解next陣列

在kmp演算法中,最關鍵的就是求解next陣列了。那麼如何快速求解next陣列呢?已知模式串 ab cdabdd a 其next陣列 00 0 0 12 0 0 1 那麼是如何求證出來的呢?首先字串從左至右遍歷。第乙個字元a的next陣列對應元素為0,第乙個字元a和第2個字元b比,不相等。b 0 表...