最長公共子串

2021-07-13 11:33:17 字數 2427 閱讀 3009

以例項說明:字串a=kitten,字串b=sitting

那他們的最長公共子串為ittn(注:最長公共子串不需要連續出現,但一定是出現的順序一致),最長公共子串長度為4。

定義:lcs(a,b)表示字串a和字串b的最長公共子串的長度。很顯然,lsc(a,b)=0表示兩個字串沒有公共部分。

rev(a)表示反轉字串a

len(a)表示字串a的長度

a+b表示連線字串a和字串b

性質:lcs(a,a)=len(a)

lcs(a,」「)=0

lcs(a,b)=lcs(b,a)

0≤lcs(a,b)≤min(len(a),len(b))

lcs(a,b)=lcs(rev(a),rev(b))

lcs(a+c,b+c)=lcs(a,b)+len(c)

lcs(a+b,a+c)=len(a)+lcs(b,c)

lcs(a,b)≥lcs(a,c)+lcs(b,c)

lcs(a+c,b)≥lcs(a,b)+lcs(b,c)

為了講解計算lcs(a,b),特給予以下幾個定義

a=a1a2……an,表示a是由a1a2……an這n個字元組成,len(a)=n

b=b1b2……bm,表示b是由b1b2……bm這m個字元組成,len(b)=m

定義lcs(i,j)=lcs(a1a2……ai,b1b2……bj),其中0≤i≤n,0≤j≤m

故:  lcs(n,m)=lcs(a,b)

lcs(0,0)=0

lcs(0,j)=0

lcs(i,0)=0

對於1≤i≤n,1≤j≤m,有公式一

若ai=bj,則lcs(i,j)=lcs(i-1,j-1)+1

若ai≠bj,則lcs(i,j)=max(lcs(i-1,j-1),lcs(i-1,j),lcs(i,j-1))

計算lcs(a,b)的演算法有很多,下面介紹的needleman/wunsch演算法是其中的一種。和ld演算法類似,needleman/wunsch演算法用的都是動態規劃的思想。在needleman/wunsch演算法中還設定了乙個權值,用以區分三種操作(插入、刪除、更改)的優先順序。在下面的演算法中,認為三種操作的優先順序都一樣。故權值預設為1。

舉例說明:a=ggatcga,b=gaattcagtta,計算lcs(a,b)

則,lcs(a,b)=lcs(7,11)=6

可以看出,needleman/wunsch演算法實際上和ld演算法是非常接近的。故他們的時間複雜度和空間複雜度也一樣。時間複雜度為o(mn),空間複雜度為o(mn)。空間複雜度經過優化,可以優化到o(m),但是一旦優化就喪失了計算匹配字串的機會了。由於**和ld演算法幾乎一樣。這裡就不再貼**了。

還是以上面為例a=ggatcga,b=gaattcagtta,lcs(a,b)=6

他們的匹配為:

如上面所示,藍色表示完全匹配,黑色表示編輯操作,_表示插入字元或者是刪除字元操作。如上面所示,藍色字元有6個,表示最長公共子串長度為6。

利用上面的needleman/wunsch演算法矩陣,通過回溯,能找到匹配字串

第一步:定位在矩陣的右下角

若ai≠bj,回溯到左上角、上邊、左邊中值最大的單元格,若有相同最大值的單元格,優先順序按照左上角、上邊、左邊的順序

若當前單元格是在矩陣的第一行,則回溯至左邊的單元格

若當前單元格是在矩陣的第一列,則回溯至上邊的單元格

依照上面的回溯法則,回溯到矩陣的左上角

第三步:根據回溯路徑,寫出匹配字串

若回溯到左上角單元格,將ai新增到匹配字串a,將bj新增到匹配字串b

若回溯到上邊單元格,將ai新增到匹配字串a,將_新增到匹配字串b

若回溯到左邊單元格,將_新增到匹配字串a,將bj新增到匹配字串b

搜尋晚整個匹配路徑,匹配字串也就完成了

ld演算法和needleman/wunsch演算法的回溯路徑是一樣的。這樣找到的匹配字串也是一樣的。

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

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...