KMP演算法及其優化

2021-10-06 21:54:09 字數 1653 閱讀 9585

今天來記錄一下,關於字元匹配的kmp演算法。

給定字串text和pattern,需要判斷字串pattern是否為test的子串。pattern一般稱為模式串,text為文字串。若匹配成功,則讓函式返回,匹配開始處的下標,否則,返回-1。

假設有乙個字串s,它以i號位作為結尾的子串就是s[1…i]。對該字串來說,長度為 k+1 的字首和字尾分別是 s[0…k] 和 s[i - k…i] 。現在定義乙個 next 陣列,其中 next[i] 表示使子串 s[0…i] 的字首 s[0…k] 等於字尾 s[i-k…i] 的最大的 k (注意:字首字尾可以部分重合,但不能是 s[0…i] 本身),如果找不到相等的前字尾,就令next[i] = -1。顯然 next[i] 就是所求最長相等前字尾中字首的最後一位的下標。

//對於next陣列而言,next[0]總是等於-1,因為對第一位來說,其不存在公共前字尾,而又為了其他位比較時,從上一位next[0]多一位的1開始比較。

void

getnext

(char pattern,

int m)

if(pattern[i]

== pattern[j +1]

) next[i]

= j;

//每次讓j記錄上一字元的next值

}return

;}

//對於該演算法,只有pattern上的指向在不斷由於i的更新改變

intkmp

(char text,

char pattern,

int n,

int m)

if(text[i]

== pattern[j +1]

)if(j == m -1)

}return-1

;//不匹配返回-1

}

上述**與求解next的**驚人的相似,其實求解next陣列的過程就是模式串pattern進行自我匹配的過程。

計算mext陣列的時間複雜度為o(m),匹配過程的時間複雜度為o(n),故kmp演算法的時間複雜度為o(m + n)。

上述**中關於匹配中回退,從匹配的角度看,每次匹配不成功,next[j]表示當模式串的 j + 1 位失配的時候,j應當退到的位置,仔細思考,每次我們退的時候,j會進行多次無意義的回退,即他總是回到 next[j] 的位置,但全然不管 pattern[j + 1] == pattern[next[j] + 1] 的情況,即這一次回退之後還是匹配不上。要讓 next[j] 進行改變,一步回退到恰當的位置,就要對 next 陣列進行變化。優化後 nextval 陣列的含義為當模式串 pattern 的 i+1 位發生失配的時候,i 應當回退到的最佳位置。

void

getnextval

(char pattern,

int m)

if(s[i]

== s[j +1]

)if(j ==-1

|| s[i +1]

!= s[j +1]

)else

}return

;}

注:nextval只是跳過了無意義的匹配,並不會導致漏解,而由nextval的含義,getnextval 和 kmp中的 while 都可以換成 if ,因為最多隻會執行一次。

經典演算法之KMP演算法及其優化

kmp演算法的具體分析見 author s email wardseptember gmail.com date 2017.12.18 kmp演算法 include include using namespace std define maxsize 50 void getnext char sub...

C 實現KMP演算法及其優化

自己寫了乙個簡潔版本,加注釋。第乙個函式是得到kmp的next陣列。1 設定next的第乙個值為 1。2 遍歷剩下的t串 3 t串前後比較,相等就在next中對應位置加1 4 不等,就回溯 t串中等價位置 void getnext string t,int next else j next j 第二...

模式匹配(kmp)及其優化

對於兩個字串s,p。想要判斷s串中是否有模式串p,正常的思路是依次遍歷,看是否能夠匹配成功。但實際上這種有回溯的模式匹配效率往往不高,故有此無回溯模式匹配演算法 乙個直接按照定義計算字首函式的演算法流程 在乙個迴圈中以 的順序計算字首函式 的值 被賦值為 為了計算當前的字首函式值 我們令變數 從最大...