乙個:介紹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...