首先碰到求兩字串最長公共連續子串的問題,然後想到原先做過的求兩字串最長公共子串行問題,所以又把演算法導論上的解法看了一下。
這兩個問題是不同的問題,求最長公共子串行不要求求得的子字串時連續的,比如說acb和ab的最長公共子串行就是ab。而最長公共連續子串,要求求得的子串在兩個字串中必須是連續出現的,還是acb和ab他們的最長公共子串是a或者是b。這裡說的是求兩字串的最長公共子串行,用的是動態規劃。
動態規劃求解最優化問題應該具備的兩個要素:最優化子結構和子問題重疊。我的理解就是碰到問題先看看能不能把大問題化解為小問題解決,這就是我對最優子結構的理解。子問題重疊意思就是說,你在求子問題的時候一些工作是重複做了,看看能不能想辦法避免以下。
對於動態規劃的運用我還不是很熟練,但我在碰到問題時往往是這樣做的:先判斷原先的問題能不能化解為小問題,如果能化為小問題的話,怎麼求解,試著寫一下(遞推)公式。如果遞推公式寫成功了的話,恰巧符合動態規劃求解。自然而然就可以應用動態規劃了。動態規劃的應用最主要的就是寫出遞推公式。
下面言歸正傳,求兩個字串的最長公共子串行。借用演算法導論上的表示方法,給定乙個字串x=(下劃線後面的數字表示下標),另乙個字串y=,求x和y的最長公共子串行。同時我們用x_i表示x中前i個字元構成的字串x_i = ,用y_j表示y紅前j個字元構成的字串y_j = 。
現在就想怎麼把問題變為為小問題呢?怎麼解決這個問題呢?
關鍵要找到問題的突破口,先不要管最終解決,先想一想怎麼吧問題花姐的規模小一些。我先分別拿兩個字串的最後乙個字元「開刀」,先拿他們比較
1)我們可以首先比較x_m和y_n如果這兩個字元相同,那麼x_m = y_n一定是最長公共子串行中的乙個字元。那麼我們的問題就是求x_(m-1) = 和y_(n-1) = 的最長公共子串行了。如果能求出x_(m-1)和y_(n-1)的最長公共子串行,這個子串行在加上字元x_m = y_n就是我們所求問題的最長公共子串行了。
2)如果x_m != y_n,我們要求x和y的最長公共最序列,就轉為求兩個子問題,乙個是求x_m和y_(n-1)的最長公共子串行,另乙個是求x_(m-1)和y_n的最長公共子串行。取兩者中最長的那個就是問題的解。
至此,大問題就化為小問題的,具體我們可以寫遞推公式。
假如用c[i,j]表示x_i和y_j序列的最大公共子串行的長度的話
c[i,j] = 0 如果i == 0或者j == 0
c[i,j] = c[i - 1][j - 1] 如果x_j == y_j
c[i,j] = max(c[i-1,j], c[i, j-1]) 如果x_i != y_j
有了遞推公式,定義對應遞推公式的陣列,就可以求得最終的答案。
#include#include#includeusing namespace std;
int max(const int& a, const int& b)
//模板函式用來輸出二維陣列
templatevoid print_vector(const vector>& vec)
cout << endl; }}
//getlcs函式用來求兩個字串的最大公共子串行,並返回其長度
int getlcs(const string& str1, const string& str2)
size_t len1 = str1.size();
size_t len2 = str2.size();
//lcs用來儲存兩字串str1[0,...,row]和str1[0,...,col]的最長公共序列的長度
vector> lcs(len1 + 1, vector(len2 + 1, 0));
//index用來儲存如何找到最長公共子串行
vector> index(len1 + 1, vector(len2 + 1, '-'));
for(size_t row = 0; row != len1 + 1; row++)
if(str1[row - 1] == str2[col - 1])
if(str1[row - 1] != str2[col - 1])
else
}} }
cout << "lcs vector is " << endl;
print_vector(lcs);
cout << "index vector is " << endl;
print_vector(index);
return lcs[len1][len2];
}int main(void)
最長公共子串行 動態規劃
經常會遇到複雜問題不能簡單地分解成幾個子問題,而會分解出一系列的子問題。簡單地採用把大問題分解成子問題,並綜合子問題的解匯出大問題的解的方法,問題求解耗時會按問題規模呈冪級數增加。為了節約重複求相同子問題的時間,引入乙個陣列,不管它們是否對最終解有用,把所有子問題的解存於該陣列中,這就是動態規劃法所...
最長公共子串行 動態規劃
關於用動態規劃法求兩個序列的最長公共子串行問題的相關知識見 王曉東 計算機演算法設計與分析 第三章。注意,這裡所指的最長公共子串行是可以不相鄰的,與平常所說的最長公共子串 相鄰的 不一樣。直接上 lcs.h ifndef lcs h define lcs h class lcstring endif...
最長公共子串行(動態規劃)
定義 乙個數列 如果分別是兩個或多個已知數列的子串行,且是所有符合此條件序列中最長的,則 稱為已知序列的最長公共子串行。考慮最長公共子串行問題如何分解成子問題,設a a0,a1,am 1 b b0,b1,bm 1 並z z0,z1,zk 1 為它們的最長公共子串行。不難證明有以下性質 1 如果am ...