动态规划----最长公共子序列问题
生活随笔
收集整理的這篇文章主要介紹了
动态规划----最长公共子序列问题
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
動態規劃算法與分治法類似,其基本思想也是將待求解的問題分解為若干個子問題,先求解子問題,然后再從若干個子問題的解得到原問題的解。與分治法不同的是,適合于用動態規劃法求解的問題,經分解得到的子規模往往不是相互獨立的。
動態規劃算法適用于解最優化的問題。通常可以按照以下步驟設計動態規劃算法:
動態規劃算法可有效解決最長公共子序列的問題。首先來看看最長公共子序列的定義:
這道題可以按照下面兩種情況分析,解決動態規劃問題最主要的是要用假設。
根據上面兩種情況分析我們可以利用歸納法寫出數學表達式:
因此根據數學表達式直接寫出代碼如下:
從運行結果我們可以看到確實計算出了X和Y的最長公共子序列的長度是4:
但是很明顯這個程序重復計算了好多次相同規模的情況,因此我們用一個二維數組來標記,減少重復計算相同規模的子序列。
這樣一來就大大提高了程序的運行效率。
但是這個時候我們只能計算出X和Y的最長公共子序列的長度,不能知道最長公共子序列是具體哪個序列,因此我們再將程序完善:
void PrintVector(vector<vector<int>>& c) {for (int i = 0; i < c.size(); i++){for (int j = 0; j < c[i].size(); j++){cout << c[i][j] << " ";}cout << endl;}cout << endl; } void PrintItem(char *X, int m, int n, vector<vector<int>> &s) {if (m == 0 || n == 0)return;else{if (s[m][n] == 1){PrintItem(X, m - 1, n - 1, s);cout << X[m] << " ";}else if (s[m][n] == 2){PrintItem(X, m - 1, n, s);}else{PrintItem(X, m, n - 1, s);}} } int lcsLength(char *X, char *Y, int m, int n, vector<vector<int>>& c, vector<vector<int>>& s) {if (m == 0 || n == 0)return 0;else if (c[m][n] > 0) return c[m][n];else{if (X[m] == Y[n]){c[m][n] = lcsLength(X, Y, m - 1, n - 1, c,s) + 1;s[m][n] = 1;//X和Y相等}else{int a = lcsLength(X, Y, m, n - 1, c, s);int b = lcsLength(X, Y, m - 1, n, c, s);if (a > b){c[m][n] = a;s[m][n] = 2;//行-1}else{c[m][n] = b;s[m][n] = 3;//列-1}}return c[m][n];} } int main() {char X[] = { "#ABCBDAB" };char Y[] = { "#BDCABA" };int mx = strlen(X) - 1;int ny = strlen(Y) - 1;vector<vector<int>> c, s;//二維數組c.resize(mx + 1);//重設容器大小并填充元素(填充vector)s.resize(mx + 1);for (int i = 0; i < mx + 1; i++){c[i].resize(ny + 1);//重設容器大小并填充元素(字符類型的缺省值)s[i].resize(ny + 1);}int maxlen = lcsLength(X, Y, mx, ny,c,s);PrintVector(c);PrintVector(s);PrintItem(X, mx, ny, s);cout << endl;cout << maxlen << endl; }非遞歸算法如下:
int NicelcsLength(char* X, char* Y, int m, int n, vector<vector<int>>& c, vector<vector<int>>& s) {for (int i = 1; i <= m; i++){for (int j = 1; j <= n; j++){if (X[i] == Y[j]){c[i][j] = c[i - 1][j - 1] + 1;s[i][j] = 1;}else if(c[i - 1][j]> c[i][j - 1]){c[i][j] = c[i - 1][j]; s[i][j] = 2;}else{c[i][j] = c[i][j - 1];s[i][j] = 3;}}}return c[m][n]; }總結
以上是生活随笔為你收集整理的动态规划----最长公共子序列问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 谷歌账户无法添加_如何将另一个Googl
- 下一篇: 搭建wiki知识库