KMP演算法 看一遍解決

2021-10-17 12:18:21 字數 3153 閱讀 2294

c語言例項

總結為什麼要用kmp演算法

kmp演算法

kmp演算法主要用於查詢字串,是 d.e.knuth、j,h,morris 和 v.r.pratt 三位神人共同提出的,稱之為 knuth-morria-pratt 演算法,簡稱 kmp 演算法。該演算法相對於 brute-force(暴力)演算法有比較大的改進,主要是消除了主串指標的回溯,從而使演算法效率有了某種程度的提高。

講kmp演算法之前,我們要先講暴力演算法

暴力演算法就是在一段文字中乙個乙個的匹配字串,匹配不成功從頭開始匹配

例如,從下**字中找到"abcabcd"

匹配第七個字元』d』時,沒匹配到,繼續從第二個位置重新開始匹配

匹配第乙個字元』a』時,沒匹配到,繼續從第三個位置重新開始匹配

匹配第乙個字元』a』時,沒匹配到,繼續從第四個位置重新開始匹配

匹配第七個字元』d』時,沒匹配到,繼續從第五個位置重新開始匹配

總共要匹配17次

int

violentmatch

(char text,

char pattern)

//text是文字串,pattern是關鍵字

else

//如果當前字元匹配失敗,pattern從頭開始匹配}if

(j == plen)

//當pattern全部匹配成功,返回匹配位置

return i - j;

else

return-1

;}

每次匹配字串失敗後都要回從頭開始匹配,如果文字串的長度是n,關鍵字的長度是m,那麼演算法效率(最差)就是n*m

我們先認識下字首

字首就是首字元直到除最後乙個字元外的任意組合都叫字首

例如"abaabbabaab",字首有"a",「ab」,「abaa」,「abaab」,「abaabb」,「abaabba」,「abaabbab」,「abaabbaba」,「abaabbabaa」

暴力演算法可以看出,有一些步驟是可以省略的

首先我們可以在關鍵字"abaabbabaab"中,找到與字首相同的組合,該關鍵字中有八組字元和字首是相同的

如下圖所示,字元下面的數字代表與字首有多少字元對應,儲存在next陣列中。

每次匹配失敗後,我們可以在匹配失敗的位置往前找有沒有和字首相同的組合,直接把整個關鍵字移到該組合的位置開始匹配,過程如下四個步驟所示

第一次匹配失敗後,在第6個字元』b』的前面找到"ab"組合是和字首相同的,那麼我們可以把整個關鍵字搬到"ab"位置上繼續匹配,如下圖

第二次匹配失敗後,在第11個字元』b』的前面找到"abaa"組合是和字首相同的,那麼我們可以把整個關鍵字搬到"abaa"位置上繼續匹配,如下圖

第三次匹配失敗後,在第5個字元』b』的前面找到"a"組合是和字首相同的,那麼我們可以把整個關鍵字搬到"a"位置上繼續匹配,如下圖

第三次匹配失敗後,在第2個字元』b』的前面沒有找到和字首相同組合,那麼按暴力演算法一樣往後移一位繼續匹配,如下圖

匹配完成,這就是kmp演算法的原理

比起暴力演算法省了很多步驟,如果關鍵字中沒有與字首相同的組合,那麼和暴力演算法沒區別

kmp能有效的減少暴力演算法中的從頭開始匹配的過程

從關鍵字中找到與字首相同的組合,每次匹配失敗後,從失敗的位置往前找到組合的位置,下次匹配的時候從該位置開始匹配

先從關鍵字中找出所有與字首相同的組合,把組合數儲存在next陣列,在匹配過程中就可以根據next陣列進行優化

//在關鍵字中記錄與字首匹配的組合,記錄在next陣列

void

match_next

(const

char

*pattern,

int*next)

if(pattern[q]

== pattern[k]

) next[q]

= k;

//next[q]對應第q個元素與字首對應數量}}

//kmp演算法

intkmp

(const

char

*text,

const

char

*pattern,

int*next)

if(pattern[q]

== text[i])if

(q == m)

}return-1

;//整個文字串找完都沒有找到字串,返回-1

}

kmp演算法就是在關鍵字中找到與字首相同的組合,儲存在next陣列,比起暴力演算法,kmp演算法可以通過next陣列,在匹配失敗後跳到該組合的位置上繼續匹配

如果文字串的長度是n,關鍵字的長度是m,那麼演算法效率是n+m

職場故事 一天看一遍

低調的力量 一壯小伙牽了一價值百萬的純種藏獒出來遛彎。逢人便炫耀狗好,人要是沒個四五百斤力量的拽都拽不住。這時候看路邊一禿頂老頭,身邊還坐乙隻毛都快要掉光了的狗。他的藏獒對那狗一頓嚎叫,那老狗理都沒理藏獒。小伙不樂意了。說道 老頭,你那狗那麼大,是什麼狗啊?咱倆的狗鬥一下?你的狗輸了給我500,我的...

每次不想學習就看一遍

你要是天天一大早六點起床,吃頓好飯,奔去教室背兩篇新三,八點坐直在教室的前排,使勁不分心不玩手機地聽完三節還是四節課,課間練字背單詞看報紙,放學奔去食堂搶份好飯,回宿舍吃完,洗洗衣服拖拖地消化下,再聽 一倍速聽完聽1.5,1.5聽完聽2倍,聽困了 歇中覺,下午繼續坐直在前排聽完三節課,放學去食堂搶個...

每天看一遍,成功的好習慣

要成功,就馬上準備有所付出吧!這就是每天你應該養成的習慣。1 不說 不可能 2 凡事第一反應 找方法,不找藉口 3 遇到挫折對自己說聲 太好了,機會來了!4 不說消極的話,不落入消極的情緒,一旦發生立即正面處理 5 凡事先訂立目標 6 行動前,預先做計畫 7 工作時間,每一分 每一秒做有利於生產的事...