演算法設計之最長公共子串行(LCS)問題

2021-06-26 03:05:06 字數 2862 閱讀 8972

先解釋一下什麼是動態規劃,動態規劃的英文名字是:dynamic programming 

,首先要說明的是這裡的

programming

和程式設計裡面的程式設計沒有關係,而是指**查詢法(

tabular method

),即將每一步計算的結果儲存在**裡,供隨後的計算查詢使用。

有動態規劃的名字可以看出它和分而治之策略之間的不同。即在動態規劃下,我們將問題分解為小問題,但是分解的小問題有許多是重複的,這樣的話用**將已經計算出的結果存起來可以節省重複計算,從而降低時間複雜性。這一點即是動態規劃提出來的乙個目的。

動態規劃提出來的另乙個主要目的是優化,即我們不只是要解決乙個問題,而是要以最優的方式解決這個問題,或者說,針對特定問題尋求特優解。

1)分析乙個最優解決方案應該具備的結構。

2)遞迴定義最優解決方案。

3)由底至上構建乙個最優解決方案。

子串(substring

):串的乙個連續的部分,

子串行(subsequence

):是從不改變序列的順序,而從序列中去掉任意的元素而獲得的新序列。

更簡略地說,子串的字元的位置必須連續,子串行則不必。

公共子串行(common subsequence

):給定兩個序列x和

y,如果z既是

x的子串行,也是

y的子串行,那麼我們稱z是

x和y的公共子串行。

最長公共子串行(longest common subsequence

):最長的公共子串行。

lcs可能不止乙個。

背景不多介紹,在生物應用中很有用,可以用於比較兩段dna

的相似程度。

先舉例,說需求。

例如兩個字串x=abcbdab 

,y=bdcaba,

序列bca是x

和y的乙個公共子串行,但是不是x和

y的最長公共子串行,子串行

bcba是x

和y的乙個lcs

,序列bdab

也是。

最長公共子串行問題就是需要在給定的兩個字串中找到最長的這樣乙個序列。

解最長公共子串行問題時最容易想到的演算法是窮舉搜尋法,即對x

的每乙個子串行,檢查它是否也是

y的子串行,從而確定它是否為x和

y的公共子串行,並且在檢查過程中選出最長的公共子串行。x和

y的所有子串行都檢查過後即可求出x和

y的最長公共子串行。

x的乙個子串行相應於下標序列

的乙個子串行,因此,x共有

2m個不同子串行(

y亦如此,如為

2^n),從而窮舉搜尋法需要指數時間(

2^m * 2^n

)。相比較於窮舉法,可以使用遞迴的思想來解決lcs

問題。遞迴的方法來解決這個問題和窮舉法比較類似,而且效率還是很低的,但是相對來說比較容易理解。

下面大致說一下演算法的思想。

人腦解決此類問題的方法就是逐個比較兩個字串的每個字元,比如str1[i]

和str2[j]

,如果str1[i]==str2[j]

,則將str1[i]

或str2[j]

附加到str1[i]

和str2[j]

之前計算得到的最長公共子串後面,然後繼續計算

str1[i+1]

開始的子串和和

str2[j+1]

開始的子串的最長公共子串。如果

str1[i]!=str2[j]

,則採用三種方法窮舉,第一種方法是刪除

str1[i]

,繼續計算

str1[i+1]

開始的子串和

str2[j]

開始的子串的最長公共子串;第二種方法是刪除

str2[j]

,繼續計算

str1[i]

開始的子串和

str2[j+1]

開始的子串的最長公共子串;第三種方法是刪除

str1[j]

和str2[j]

,繼續計算

str1[i+1]

開始的子串和

str2[j+1]

開始的子串的最長公共子串。使用三種方法計算完成後比較結果,取最長的子串附加到

str1[i]

和str2[j]

之前計算得到的最長公共子串後面組成新的最長公共子串。以上繼續計算都是遞迴過程,遞迴的終止條件即遞迴基是到達

str1

字串結尾或

str2

字串結尾。

實現**:

#include#includeusing namespace std;

void recursionlcs(const std::string& str1, const std::string& str2, std::string& lcs);

string getlongeststring(std::string& str1, std::string& str2,std::string& str3);

int main()

cout << endl;

} void recursionlcs(const std::string& str1, const std::string& str2, std::string& lcs)

else

void dynamiclcs(const std::string& x, const std::string& y, std::string& lcs)

} int i =0,j = 0;

while (i< x.length()&&j= opt[i][j+1])

i++;

else

j++;

}}

演算法 最長公共子串行LCS

演算法 最長公共子串行 子串行的定義 如果z是a的子串行,則a中包含z的所有排列元素,且這些元素在各自排列中的順序是一致的 例如z a 最優子結構 設c是lcs的長度 則if i 0 j 0 c i,j 0 else if x i y j c i,j c i 1,j 1 1 else if x i ...

最長公共子串行LCS演算法

思路 對所有子問題s1 1 i 和s2 1 j 進行求解。s1 1 i 表示1 i範圍的s1子串,s2 1 j 表示1 j範圍的s2子串。舉例 define n1 8 define n2 9 int s1 n1 1 int s2 n2 1 其所有子問題如下 s1 1 1 s2 1 1 求其最長公共子...

LCS演算法最長公共子串行

問題 求解x和y的最長公共子串行 解析先處理序列的前 公式 個元素組成的子串行,然後再依次往上加後面的元素。即,用 公式 表示序列1和序列2前 公式 個元素的lcs長度,然後將 公式 用 公式 至 公式 表示。但是這個拆分有個問題 序列1和序列2的長度可能不等。這個問題很好解決,我們可以在較短序列的...