字串匹配 KMP演算法

2021-06-25 08:37:01 字數 2453 閱讀 2487

bf演算法
在字串匹配中,最簡單、最原始的演算法就是bf(brute force)演算法。bf演算法的基本思想就是:將目標串的第乙個字元和模式串的第乙個字元比較,若相等,則依次比較目標串和模式串的下乙個字元,直到模式串的結束位置;否則,將模式串的第乙個字元和目標串上次開始比較位置的下乙個位置的字元進行比較。重複以上過程,一直到在目標串中找到模式串或者到目標串結束。
原始碼如下:

char* bfmatch(const char* str,const char* pattern)

if(j == patlen)

}return result;

}

很明顯,bf演算法的時間複雜度為0(strlen(str) * strlen(pattern)),空間複雜度o(1)。同時在上面比較過程中重複比較次數較多,沒有用上歷史的比較資訊。為了改進上面的缺陷,就有了下面的kmp演算法。

kmp演算法

在s=」abcabcabdabba」中查詢t=」abcabd」,如果使用kmp匹配演算法,當第一次搜尋到s[5] 和t[5]不等後,s下標不是回溯到1,t下標也不是回溯到開始,而是根據t中t[5]==』d』的模式函式值,直接比較s[5] 和t[2]是否相等,因為相等,s和t的下標同時增加;因為又相等,s和t的下標又同時增加,最終在s中找到了t。如圖:

第一趟匹配:

第二趟匹配:

此時又該如何確定當失配時,模式串的移動距離呢?下面將說明如何求next陣列,以及為什麼目標串不需要回溯。

假設目標串str從位置i開始和模式串pattern比較,在位置j(j >= i)處,模式串和目標串不匹配,即pattern[j - i - 1] != str[j]。此時,str[i,j-1] = pattern[0,j - i-1]成立。

假設存在k使pattern[0,j - i - k - 1] = pattern[k ,j-i-1]成立,並且j - i - k最大,則此時可以將pattern[k]和str[j]進行比較(為什麼目標串不需要回溯呢?反證法證明)假設從目標串第i + x(x < k)處開始可能存在著和模式串完全匹配的子串,則str[i + x,j - 1] = pattern[0, j - i - x - 1] = str[i,j - i - x] = pattern[x ,j - i - 1],由於j - i - k > j - i - x,所以k < x,這與假設矛盾。注:這裡不考慮k < x的原因是因為處於x位置的情況後面將要考慮,但處於k前面的位置將要被我們跳過,但要證明被跳過的位置是正確的,所以只考慮k前面的位置。

以上證明說明了我們只要找到最大的k,使pattern[0.k - 1] = pattern[j - k,j - 1]即可,此時k值為子串pattern[0,j-1]最長的相等字首和字尾的長度。如何計算next呢?這裡採用了乙個技巧,根據前一次的的結果來計算。當i - 1位置的最大k值為j,即next[i - 1] = j,那麼next[i]的計算就可以根據next[i - 1]來計算,當pattern[i - 1] = pattern[j]時,由next[i - 1] = j,可知pattern[0,j - 1] = pattern[i - j ,i - 2],所以pattern[0,j] = pattern[i - j - 1,i - 1],因此next[i] = j + 1;當pattern[i - 1] != pattern[j]時,此時需要算pattern[next[i - 1]]與pattern[i-1]的關係。**如下:

void getnext(const char* pattern,int len,int *next)

else j = next[j];}}

當求出next陣列時,那就可以進行字串匹配了,

char* getkmpmatch(const char* str,const char* pattern)

else

}if( j >= patlen)

result = (char*)str + i - patlen;

free(next);

return result;

}

求next陣列的改進
我們再看一種情況,str = "aaabaaaab",pattern = "aaaab",利用上述方法則求的next陣列為next = ,當i = 3,j = 3時,此時匹配失效,並且按照next陣列此時需要三次比較,而實際情況只需i = 4,j = 0比較即可。當pattern[i] = pattern[j]時,當匹配時,pattern[i]失效,則j = next[i]時也會失效。

void getnext(const char* pattern,int len,int *next)

else j = next[j];}}

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的第乙個字元,依次比較下去,直到得出最後的匹配...