資料結構 字串模式匹配的KMP演算法

2021-08-19 11:53:47 字數 2691 閱讀 5291

kmp演算法是模式匹配的一種演算法,他的思想是,當我們進行模式匹配的時候,不用像暴力解法那樣乙個乙個字元去比較,而是從前一串字元的最大前字尾開始匹配,這樣就節省了不少時間

數學推導:

假如i代表主串指標,j代表子串指標

如果有:

i2 == j2;

j1 != j2;

那麼i2 != j1,我們在後乙個字元失配 的時候,可以直接跳過i2

先來看暴力演算法

//擷取字串//

status substring(string a, int pos,int t,string b)

for (i = pos,j =0 ; t > 0; t--,i++,j++)

b[j] = '\0';//這一步一定要有,沒有的話就會變成燙

return ok;

}//模式匹配的暴力演算法//

status brute_force(string a, string b, int pos)

else

} //執行到這裡代表沒找到

printf("\n不匹配\n");

return error;

}}

接下來看kmp演算法,kmp演算法分兩部分,第一部分是求next陣列,也就是當某乙個位置失配的時候,應該直接跳到子串的哪乙個位置進行比較(這裡說的就是失配的那個位置)。。

next陣列第乙個元素都是等於0的,第0個元素不用管,後面的元素就是前面的字串最大匹配的前字尾數量加一。

比如第二個字元和第乙個字元不一樣,那麼第二個字元前面的字串數量就是1(只有乙個字元),但是匹配的前字尾為0(1個字元不存在匹配的前字尾),那麼next[2]=0+1=1;

next陣列的寫入函式:

//next陣列的實現

void get_next(string b,int *next)

else

}}

然後就是kmp演算法,當我們得到了next陣列之後,就可以用陣列進行模式匹配,還是和暴力解法一樣,ij分別指向主串和子串(模式串),加入相等就ij分別加一,不相等就用next陣列為嚮導對模式串進行指南(指導它該從哪乙個位置開始進行比較)。

//kmp演算法主函式

status index_kmp(string a, string b, int pos)

else

} //跳出迴圈的時候如果j大於子串長度則表示匹配

if (j > b[0])

else

}

但是,我們的next函式是可以進行改進的。

原理是這樣的,假如i3 != j3,j2 == j3,那麼,j2 != i3,也就是說此時重複的比較就是多餘並且可以去掉的

改進next函式的思路是:在進行next賦值的時候我們要多考慮一步,如果將要賦值的字尾和加一後的字首相等的話,那麼他們的next值實際上應該是一樣的,如果不這麼做的話,實際上執行kmp演算法的時候會先指導到前乙個相同的字元,然後再執行它的next陣列值,這樣做就很多餘而且浪費時間。

//改進之後的next函式

void get_nextval(string b, int *nextval)

else

} else

}}

下面附上所有的**

#include "stdafx.h"

#include #include #include #define ok 1

#define error 0

#define maxsize 20

typedef char elemtype;

typedef char string;

typedef int status;

//擷取字串//

status substring(string a, int pos,int t,string b)

for (i = pos,j =0 ; t > 0; t--,i++,j++)

b[j] = '\0';//這一步一定要有,沒有的話就會變成燙

return ok;

}//模式匹配的暴力演算法//

status brute_force(string a, string b, int pos)

else

} //執行到這裡代表沒找到

printf("\n不匹配\n");

return error; }}

//kmp演算法//

//next陣列的實現

void get_next(string b,int *next)

else }}

//改進之後的next函式

void get_nextval(string b, int *nextval)

else

} else }}

//kmp演算法主函式

status index_kmp(string a, string b, int pos)

else

} //跳出迴圈的時候如果j大於子串長度則表示匹配

if (j > b[0])

else

}int main()

輸出結果:

資料結構 字串匹配KMP

kmp主要用於字串匹配 關鍵在於next陣列的求解,當匹配不成功的時候模式串的回退位置就由next陣列決定。next陣列只與主串有關,其求解過程就運用到了kmp思想,求解過程網上很多,個人覺得比較難以理解。next陣列應用,下標從1開始 字首與字尾的最大匹配長度,next i 為字首與字尾的最長匹配...

資料結構 字串 模式匹配

我們先把模式串標出序號 接著把模式串所有字首依次列出來 接下來把每乙個子串相等的字首和字尾的最大長度求出,舉個例子 abaab 觀察子串,前字尾ab相同,因此返回2 5.依次類推,我們可以得到每乙個子串對應的一組序列 當時這組資料並不是所要求的next陣列,可以將其稱為部分匹配值表,相應c 如下 獲...

演算法與資料結構 字串模式匹配 KMP 演算法

在乙個很長的字串 t 中,查詢是否存在子字串 p。例如搜尋引擎收錄的大量 資料,當使用者輸入關鍵字後,就會在這些資料中進行匹配,並返回合適的 語義 假定字串長度為 j,則所有字串都在 0,j 這樣的集合中。返回首次匹配的字元的位置。注意這裡呼叫方需要判斷位置是否正確,例如對於長度為 i 的字串,要查...