演算法 KMP演算法完全解析(C語言實現)

2021-10-19 02:52:36 字數 3175 閱讀 7669

kmp演算法所做的事情,就是在字串中尋找子串。比如ilovecode這個字串中,我們可以搜尋到love這個子串。但如果用回溯的暴力方法尋找子串(即兩個for迴圈),雖然思路簡單,但是時間複雜度為o(m*n)。借助kmp演算法,可將複雜度降為乙個迴圈,增進了效率。

(1)字首和字尾的概念:

*字首:指的是從首字元開始往後的子字串(不包括尾字元)。比如lwcsb的字首就是l、lw、lwc和lwcs,lwcsb不是字首。

*字尾:與字首相同,類推。lwcsb的所有字尾有 b , sb , csb , wcsb 。

(2)最長相等前字尾的概念:

比如aaba,字首有a , aa , aab;字尾有a , ba , aba。

上下(前後)匹配的最長長度1。

(3)字首表:

就是乙個字串從前到後所有字首字串的最長相等前字尾數字所組成的表。

實現kmp的高效演算法,我們必須借助字首表,也就是所謂的「next陣列」。

用兩個遍歷頭 i , j 指示前字尾的末位。注意,i既表示字首的末位,也表示字首的長度,利用這一點,我們可以對應填入next陣列的值。在填充過程中,我們需要討論兩種情況:

<1>i,j所指示的字元不相等:i需要退位,退到相應位置之後再進行賦值。

<2>i,j所指示的字元相等:i進製,用i賦值next[j]。

【上述兩點總結起來就是:(i退位 -> 賦值 -> j自增)和(i自增 -> 賦值 -> j自增)】

*光這樣說說肯定不知所云一頭霧水。讓我來將這個過程例項化:

*****可以看出,整個這乙個建立next陣列(字首表)的過程,其實有四個關鍵:

<1>初始化:i,j和next[0]=0。

<2>判斷討論。

<3>j迴圈後移,i持續退位。

<4>賦值:next[j]=i。(原理是:i本身的值就表示了最長公共子串的長度!)

理解了這些內容,**順理成章:

void

get_nextarray

(char str,

int len,

int next)

//獲取字串str的字首表next

else

if(str[i]

!=str[j]

)//不相同

}else

continue

; next[j]

=i;//賦值

}}

我們要使用之前建立的「字首表」。如何使用呢?長串與子串一同遍歷,直到遍歷到出現不同元素為止。此時子串呼叫next陣列,子串遍歷開始的下標變為next[j-1](即當前元素的前乙個元素next陣列元素的數字,這個數字表示接下來開始遍歷的子串的起始位置的下標)

——讓ch[m]子串去匹配str[n]長串。

(1)定義兩個遍歷頭i和j,分別遍歷str和ch。

(2)全過程分為兩個過程:同步遍歷和ch子串的跳轉(使用next)

(3)while迴圈控制str和ch的同步遍歷,一旦出現不相等的情況,ch子串就要跳轉(看前乙個元素的next),i與j重新對其,繼續執行while的迴圈。

(4)結束標誌:如果i控制的子串能夠遍歷到串尾,那麼說明str中找到了對應的子串,那麼搜尋成功,跳出迴圈,結束程式;如果j控制的長串遍歷結束,i控制的子串也沒能遍歷到末尾,那麼搜尋失敗,結束程式。

請看**:

#include

#include

void

get_nextarray

(char str,

int len,

int next)

//獲取字串str的字首表next

else

if(str[i]

!=str[j]

)//不相同

}else

continue

; next[j]

=i;//賦值}}

intmain

(void

) */

char str[

1000];

//長串

char ch[

1000];

//子串

printf

("please input long string:");

gets

(str)

;printf

("please input substring:");

gets

(ch)

;printf

("\n-------------------------------------\n");

int len=

strlen

(str)

;int len=

strlen

(ch)

;int next[len]

;//子串字首表

get_nextarray

(ch,len,next)

;int i,j;

//i遍歷長串str,j遍歷子串ch

i=j=0;

int flag=0;

//標誌變數

while

(j<=len-1)

if(str[i]

==ch[j]

)//相同則往後繼續遍歷

else

//不相同,則j控制的子串需要跳轉

else}if

(i==len-1)

break;}

//出迴圈後,如果標誌變數為0,說明一次也沒有匹配到。反之已經匹配到。

if(flag==0)

else

return0;

}

測試樣例輸出:

KMP演算法詳解(C語言實現)

kmp的演算法分析 kmp解決問題 清除bf演算法中主串s指標出現的回溯情況,即當主串s和子串t在某個字元不匹配的時侯,主串s的指標位置不變,改變子串t的指標位置,使主串和子串的字元匹配 演算法思路 建立乙個next陣列,當出現主串字元與子串字元不匹配時,將模式串t的指標 j 移動到next j 的...

c語言kmp演算法

kmp是一種可以在字串中迅速找到某乙個指定的連續字串的演算法。要理解這個演算法首先要了解如何得到字串的next值。傳統的匹配方法中,每與字串進行一次未完全匹配的比較,都要從頭開始再進行一次,於是kmp就有next陣列來避免這種重複的比較,進而降低時間複雜度。next陣列的含義 與字串相對應的下標表示...

完全搞懂KMP演算法

在串的模式匹配演算法中,kmp演算法稱得上是經典演算法了。簡約而不簡單,是對kmp演算法最恰當的評價。該演算法是由d.e.knuth,j.h.morris和v.r.pratt三人同時發現,因此人們稱它為kmp演算法。廢話不多說,現在開始進入正題。首先宣告兩點 字串 採用定長順序儲存結構,主串用s表示...