一臉???演算法之KMP演算法詳解

2021-10-03 14:48:49 字數 2456 閱讀 6675

本人在學習資料結構kmp演算法這節內容時,也是花費了好長時間才弄懂,期間一直是懵的很吶!不知道大家有沒有這麼個感覺,好像有點明白kmp演算法的思想,但是再面對那幾行簡短的**是還是有點不知其所以然的感覺。所以呢,我就想給大家講解一下kmp演算法的思想及**的實現過程,讓大家少走彎路,早日豁然開朗。

簡單模式匹配(bf演算法)想必大家都應該很清楚吧,但是這種演算法效率比較低,給大家舉個例子。先定義兩個字串s、t,然後我們來看看簡單模式匹配的匹配過程。

那我們能不能根據模式串中的元素得到一些資訊從而來減少一些不必要的匹配操作呢?答案是肯定的,我們可以引入kmp演算法來解決這個問題,kmp演算法的關鍵就是如何獲取next陣列,上面的例子不夠典型,下面我就舉幾個例子來說明如何求得next陣列。先定義兩個字串s、t(這個例子是看的乙個博主寫的,覺得比較典型,就搬過來了,嘻嘻),如果按照簡單模式匹配,那麼其匹配過程如下:

從匹配過程中我們可以看出第一次匹配失配的位置是在第六位元素(字串第零位元素為字串的長度),在第一次匹配的過程中,我們發現模式串前五個元素與目標串前五個元素一一匹配,同時前五個元素存在重複部分,即字首和字尾都為ab(從第一位元素算起為字首,是絕對的,字尾要從該元素前一位算起,是相對的),為了減少一些不必要的匹配,我們希望下一次匹配可以從s串的第四位開始重新匹配:

在第二次匹配過程中,我們發現失配位置在第十一位元素,那麼我們就希望下一次匹配在這個位置:

那麼下下次匹配我們就希望在這個位置:

由於第二位元素失配前只有元素a,因此下次匹配只需要下移一位即可,即:

這就是kmp演算法的思想,如何實現就要利用next陣列,從上面的例子我們可以看出,匹配的過程主要是通過模式串的元素的前字尾來實現的,因此,獲取next陣列只需要關注模式串。上例中next陣列值為:

再舉乙個:

下面就來介紹一下**的實現過程,首先講解一下獲取next陣列的函式:

void

get_next

(string t,

int*next)

else

//失配,字首回溯

}}

int

kmp(string s,string t,

int pos)

else

//當前匹配失敗,則有next陣列指引相應元素去匹配

//如:s:abababcababc

// t:ababaaaba (next:011234223)

//若在第六位元素發生失配,此時i=j=6,j=next[6]=4

//則由t串第四位元素與s串第六位元素開始匹配,即:

//s:abababcababc

//t: ababaaaba }if

(j>t[0]

)//匹配完成

else

//匹配失敗

}

kmp演算法還可以進一步優化,比如遇到下面這個例子時:

這種情況下,kmp演算法的效率也比較低,t串第五位與s串第五位元素不匹配,s串前五位元素相等,因此自然也和第六位元素不匹配,為減少一些不必要的匹配,可在獲取next陣列的函式中做出如下改進:

void

get_next

(string t,

int*next)

else

}else

//失配,字首回溯

}}

此時:

最後博主希望你們:

看之前:

看完後:

一臉懵逼的演算法系列之漢諾塔

法國數學家愛德華 盧卡斯曾編寫過乙個印度的古老傳說 在世界中心貝拿勒斯 在印度北部 的聖廟裡,一塊黃銅板上插著三根寶石針。印度教的主神梵天在創造世界的時候,在其中一根針上從下到上地穿好了由大到小的64片金片,這就是所謂的漢諾塔。不論白天黑夜,總有乙個僧侶在按照下面的法則移動這些金片 一次只移動一片,...

演算法小白KMP入門(捂臉)

先放題吧.給定乙個字串 模式串 和一些待查詢的字串,求每個待查詢字串在模式串中出現的次數 可重疊 測試資料有多組 測試組數 5 第一行包括乙個字串p,長度不超過105,且非空串 第二行包括乙個整數n,代表待查詢的字串數量 1 n 5 接下來的n行,每一行包括乙個待查詢的字串,其長度不超過50,且非空...

KMP演算法詳解

模式匹配的kmp演算法詳解 這種由d.e.knuth,j.h.morris和v.r.pratt同時發現的改進的模式匹配演算法簡稱為kmp演算法。大概學過資訊學的都知道,是個比較難理解的演算法,今天特把它搞個徹徹底底明明白白。注意到這是乙個改進的演算法,所以有必要把原來的模式匹配演算法拿出來,其實理解...