字串匹配演算法 KMP學習心得

2021-05-04 09:51:44 字數 1607 閱讀 4484

2023年4月22日 12:56

slyar

kmp演算法是一種改進的字串匹配演算法,由d.e.knuth與v.r.pratt和j.h.morris同時發現,因此人們稱它為克努特—莫里斯—普拉特操作(簡稱kmp演算法)。

這週的資料結構課講的是串,本以為老師會講解kmp演算法的,誰知到他直接略過了...沒辦法只能自己研究,這一琢磨就是3天,期間我都有點懷疑自己的智商...不過還好昨天半夜終於想明白了個中緣由,總結一些我認為有助於理解的關鍵點好了...

書上有的東西我就不說了,那些東西網上一搜一大片,我主要說一下我理解的由字首函式生成的next陣列的含義,先貼出求next陣列的方法。

123

4567

891011

1213

1415

1617

1819

20

void getnext(

char

* t,

int* next)

else

}}

當乙個字串以0為起始下標時,next[i]可以描述為"不為自身的最大首尾重複子串長度"。

也就是說,從模式串t[0...i-1]的第乙個字元開始擷取一段長度為m(m < i-1)子串,再擷取模式串t[0...i-1]的最後m個字元作為子串,如果這兩個子串相等,則該串就是乙個首尾重複子串。我們的目的就是要找出這個最大的m值。

例如:若 i = 4 ,則 i - 1 = 3 , m = next[4] = 2

從t[0...3]擷取長度為2的子串,為"ab"

從t[0..3]擷取最後2個字元,為"ab"

此時2個子串相等,則說明 next[4] = 2 成立,也可證明 m = 2 為最大的m值。

本來一開始我是沒有加"不為自身"這個限制條件的,可是後來我發現一種情況:

若 i = 4 ,則 i - 1 = 3 , m = next[4] = 3

從t[0...3]擷取長度為3的子串,為"aaa"

從t[0..3]擷取最後3個字元,為"aaa"

此時2個子串相等,則說明 next[4] = 3 成立。

但是我發現如果next[4] = 4:

從t[0...3]擷取長度為4的子串,為"aaaa"

從t[0..3]擷取最後4個字元,為"aaaa"

此時2個子串也是相等的,那麼是不是說明 next[4] 應該等於4呢?

仔細觀察後發現,如果 next[4] = 4 ,那麼t[0...3]的前4個字元和後4個字元是重合的,並且重複子串和t[0...3]也是相等的。看過教材後發現教材中給出的字首函式定義有一句為:next[j] = max,應該不包含子串為本身的情況...

這樣再做pku 2406 和 pku 1961 的時候就很簡單了,用 length - next[length] 求出"不為自身的最大首尾重複子串長度",此時需要多求一位next[length]值,若最大重複子串的長度是length的非1整數倍,則證明字串具有週期重複性質。

pku 2752 是求 字首 == 字尾 的長度,也就是首尾重複子串長度,利用next陣列記錄的"不為自身的最大首尾重複子串長度"可以馬上得到結果。

恩,先說這麼多吧,可能有不對的地方,以後理解的更深了再回來改...哪位大牛路過看到錯誤請指出哈。

KMP演算法 字串匹配

kmp演算法基本思想 我們在用常規的思想做 字串匹配時候是 如 對如 字元如果 t abab 用p ba 去匹配,常規思路是 看 t 第乙個元素 a 是否 和p 的乙個 b 匹配 匹配的話 檢視各自的第二個元素,不匹配 則將 t 串的 第二個元素開始 和 p 的第乙個匹配,如此 一步一步 的後移 來...

KMP字串匹配演算法

kmp核心思想 計算模式串的next陣列,主串的索引在比較的過程中不回朔 ifndef kmp h define kmp h class kmp endif include kmp.h include include include using namespace std int kmp calcu...

KMP字串匹配演算法

在介紹kmp演算法之前,先介紹一下bf演算法。一.bf演算法 bf演算法是普通的模式匹配演算法,bf演算法的思想就是將目標串s的第乙個字元與模式串p的第乙個字元進行匹配,若相等,則繼續比較s的第二個字元和p的第二個字元 若不相等,則比較s的第二個字元和p的第乙個字元,依次比較下去,直到得出最後的匹配...