KMP該演算法解釋 最長公共子

2021-09-08 17:34:02 字數 4191 閱讀 9740

乙個:介紹kmp演算法之前,首先解釋一下bf演算法

(1)bf演算法(傳統的匹配演算法,是最簡單的演算法)

bf演算法是一種常見的模式匹配演算法,bf該演算法的思想是目標字串s模式串的第乙個字元p的第乙個字元,以匹配,如果相等,然後去比較s第二個字和p;若不相等。則比較s的第二個字元和p的第乙個字元。依次比較下去。直到得出最後的匹配結果。

(2)舉例說明:

s:  ababcababa

p:  ababa

bf演算法匹配的過程例如以下

i=0                  i=1                       i=2                 i=3                   i=4

第一趟:ababcababa         第二趟:ababcababa      第三趟:ababcababa    第四趟:ababcababa    第五趟:ababcababa

ababa                         ababa                 ababa                 ababa                   ababa

j=0                           j=1                   j=2                   j=3                     j=4(i和j回溯)

i=1                           i=2                   i=3                   i=4                     i=3

第六趟:ababcababa         第七趟:ababcababa       第八趟:ababcababa     第九趟:ababcababa   第十趟:ababcababa

ababa                   ababa                        ababa               ababa                   ababa

j=0                     j=0                          j=1                 j=2(i和j回溯)           j=0

i=4                     i=5                          i=6                 i=7                     i=8

第十一趟:ababcababa       第十二趟:ababcababa    第十三趟:ababcababa   第十四趟:ababcababa   第十五趟:ababcababa

ababa                    ababa               ababa                    ababa                ababa

j=0                       j=0                j=1                      j=2                  j=3

i=9第十六趟:ababcababa

ababa

j=4(匹配成功)

事實上在上面的匹配過程中,有非常多比較是多餘的。在第五趟匹配失敗的時候,在第六趟。i能夠保持不變。j值為2。由於在前面匹配的過程中,對於串s,已知s0s1s2s3=p0p1p2p3。又由於p0!=p1!。所以第六趟的匹配是多餘的。又由於p0==p2,p1==p3,所以第七趟和第八趟的匹配也是多餘的。

在kmp演算法中就省略了這些多餘的匹配。

(3)bf**:

int bfmatch(char* ori,char *des)

if(*(des+j)=='\0')

return i-j;// 返回匹配成功後的src中的開始下標

i = i-j+1;// 回溯到,這次匹配的src中的開始位置的下乙個位置

}return -1;

}

二:kmp演算法

(1)kmp演算法之所以叫做kmp演算法是由於這個演算法是由三個人共同提出來的,就取三個人名字的首字母作為該演算法的名字。

事實上kmp演算法與bf演算法的差別就在於kmp演算法巧妙的

消除了指標i的回溯問題。僅僅需確定下次匹配j的位置就可以。使得問題的複雜度由o(mn)下降到o(m+n)。

在kmp演算法中,為了確定在匹配不成功時,下次匹配時j的位置,引入了next陣列,next[j]的值表示p[0...j-1]中最長字尾的長度等於同樣字串行的字首。

對於next陣列的定義例如以下:

1) next[j] = -1  j = 0

2) next[j] = max(k): 00時,表示p[0...k-1]=p[j-k,j-1]

因此kmp演算法的思想就是:在匹配過程稱,若發生不匹配的情況,假設next[j]>=0,則目標串的指標i不變。將模式串的指標j移動到next[j]的位置繼續進行匹配;若next[j]=-1,則將i右移1位,並將j置0,繼續進行比較。

(2)kmp演算法通過next陣列能夠知道目標串中下乙個字元是否有必要被檢測,這個next陣列就是用所謂的「字首函式(一般資料結構書中的getnext函式)」來儲存的。

這個函式可以反映出現失配情況時,系統應該跳過多少無用字元(也即模式串應該向右滑動多長距離)而進行下一次檢測

一是這個字首函式的求法。

二是在得到字首函式之後。怎麼運用這個函式所反映的有效資訊避免不必要的檢測。

以下介紹《部分匹配表》是怎樣產生的。

首先,要了解兩個概念:"字首"和"字尾"。 "字首"指除了最後乙個字元以外,乙個字串的所有頭部組合。"字尾"指除了第乙個字元以外,乙個字串的所有尾部組合。

"部分匹配值"就是"字首"和"字尾"的最長的共同擁有元素的長度。以"abcdabd"為例,

- "a"的字首和字尾都為空集,共同擁有元素的長度為0。

- "ab"的字首為[a],字尾為[b],共同擁有元素的長度為0;

- "abc"的字首為[a, ab]。字尾為[bc, c]。共同擁有元素的長度0。

- "abcd"的字首為[a, ab, abc],字尾為[bcd, cd, d],共同擁有元素的長度為0;

- "abcda"的字首為[a, ab, abc, abcd],字尾為[bcda, cda, da, a]。共同擁有元素為"a",長度為1;

- "abcdab"的字首為[a, ab, abc, abcd, abcda],字尾為[bcdab, cdab, dab, ab, b]。共同擁有元素為"ab",長度為2;

- "abcdabd"的字首為[a, ab, abc, abcd, abcda, abcdab],字尾為[bcdabd, cdabd, dabd, abd, bd, d],共同擁有元素的長度為0。

(3) **例如以下:

#include #include using namespace std;

const int max_size = 64;

void getnext(char *p,int next)

(4)總結:kmp是用來匹配test字串是否是目標串的子串,相當於全然匹配。即測試字串是否在目標字串**現過

三:最長公共子串行(longest commen subsequence)

(1)子串行:不要求連續的,子串是要求連續的。

(2)**例如以下:

#include #include #include #include using namespace std;

const int max_size = 100;

int lcslength(char *s1,char *s2,const int &len1,const int &len2,int lcs[max_size],int b[max_size])

else if(lcs[i-1][j] >= lcs[i][j-1])

else}}

return lcs[len1][len2];

}void printlcs(char *s1,int b[max_size],int i,int j)

else if(b[i][j] == 1)

else

}int main()

return 0;

}//

最長公共子串行 最長公共子串

1 最長公共子串行 採用動態規劃的思想,用乙個陣列dp i j 記錄a字串中i 1位置到b字串中j 1位置的最長公共子串行,若a i 1 b j 1 那麼dp i j dp i 1 j 1 1,若不相同,那麼dp i j 就是dp i 1 j 和dp i j 1 中的較大者。class lcs el...

最長公共子串行 最長公共子串

1.區別 找兩個字串的最長公共子串,這個子串要求在原字串中是連續的。而最長公共子串行則並不要求連續。2 最長公共子串 其實這是乙個序貫決策問題,可以用動態規劃來求解。我們採用乙個二維矩陣來記錄中間的結果。這個二維矩陣怎麼構造呢?直接舉個例子吧 bab 和 caba 當然我們現在一眼就可以看出來最長公...

最長公共子串 最長公共子串行

子串要求連續 子串行不要求連續 之前的做法是dp求子序列 include include include using namespace std const int inf 0x3f3f3f3f const int mod 1000000007 string s1,s2 int dp 1010 10...