經常會遇到複雜問題不能簡單地分解成幾個子問題,而會分解出一系列的子問題。簡單地採用把大問題分解成子問題,並綜合子問題的解匯出大問題的解的方法,問題求解耗時會按問題規模呈冪級數增加。
為了節約重複求相同子問題的時間,引入乙個陣列,不管它們是否對最終解有用,把所有子問題的解存於該陣列中,這就是動態規劃法所採用的基本方法。
【問題】
求兩字串行的最長公共字元子串行
求解:引進乙個二維陣列c,用c[i][j]記錄x[i]與y[j] 的lcs 的長度,b[i][j]記錄c[i][j]是通過哪乙個子問題的值求得的,以決定搜尋的方向。
我們是自底向上進行遞推計算,那麼在計算c[i,j]之前,c[i-1][j-1],c[i-1][j]與c[i][j-1]均已計算出來。此時我們根據x[i] = y[j]還是x[i] != y[j],就可以計算出c[i][j]。
問題的遞迴式寫成:
回溯輸出最長公共子串行過程:
演算法分析:
由於每次呼叫至少向上或向左(或向上向左同時)移動一步,故最多呼叫(m + n)次就會遇到i = 0或j = 0的情況,此時開始返回。返回時與遞迴呼叫時方向相反,步數相同,故演算法時間複雜度為θ(m + n)。
利用求最長公共子串行求單調遞增最長子序列**:
#include#include#include#include#includeusing namespace std;
char str[27];
int istr;
int l[10005][27];//長度length
void lcs_l(char a[10005],char b[27])
}void lcs_str(char a[10005],char b[27],int i,int j)
else if(l[i-1][j]>l[i][j-1])
else
lcs_str(a,b,i,j-1);
}int main(void)
// system("pause");
return 0;
}
參考: 最長公共子串行 動態規劃
關於用動態規劃法求兩個序列的最長公共子串行問題的相關知識見 王曉東 計算機演算法設計與分析 第三章。注意,這裡所指的最長公共子串行是可以不相鄰的,與平常所說的最長公共子串 相鄰的 不一樣。直接上 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 ...
最長公共子串行(動態規劃)
問題描述 使用動態規劃演算法解最長公共子串行問題,具體來說就是,依據其遞迴式,自底向上的方式依次計算得到每個子問題的最優值。輸入形式 在螢幕上輸入兩個序列x和y,序列各元素數間都以乙個空格分隔。輸出形式 矩陣c,其中c i,j 中存放的是 序列xi 和序列yj 的最長公共子串行的長度。序列x和y的最...