1. 程式人生 > >最長共同子序列LCS—動態規劃實現

最長共同子序列LCS—動態規劃實現

內容會持續更新,有錯誤的地方歡迎指正,謝謝!

前言:博主最近正在學習《演算法》這門專業課程,這是該課程的第三次上機題目,我把自己的解題方法分享給大家,歡迎討論!

題目:
描述並實現最長共同子序列動態規劃演算法,並顯示S1=ACCGGTCGAGATGCAG,S2 = GTCGTTCGGAATGCAT 的最長共同子序列。

最終結果:
最長共同子序列:CCGGGAATGCA
長度:11

該題的遞推式:
這裡寫圖片描述

根據該遞推式,便可寫出基於遞迴的動態規劃程式碼,此處省略該程式碼。我們用基於迭代的動態規劃程式碼試試:

基於迭代的動態規劃(自底向上型別)程式碼:

#include <iostream>
#include <vector> using namespace std; int lcs(string A, string B) { vector<vector<int> > len; len.resize(A.size() + 1);//初始化第一維,調整容器的長度大小,使其能容納A.size() + 1個元素 for (int i = 0; i <= A.size(); ++i) //初始化第二維 { len[i].resize(B.size() + 1, 0);//多一個引數0,將未初始化的元素初始化為0 } for
(int i = 1; i <= A.size(); ++i)//填表,如下方圖 { for (int j = 1; j <= B.size(); ++j) { //兩個字元若相等,則取(左上角元素+1)賦給自己 if (A[i - 1] == B[j - 1]) { len[i][j] = len[i - 1][j - 1] + 1; } //兩個字元若不相等,則上方元素和左方元素相比,誰大取誰 else
if (len[i - 1][j] >= len[i][j - 1]) { len[i][j] = len[i - 1][j]; } else { len[i][j] = len[i][j - 1]; } } } int aPos = A.size(); int bPos = B.size(); int commonLen = len[aPos][bPos];//最後一個元素的值就是最長共同子序列的長度 int k = commonLen; vector<char> common;//共同子序列 common.resize(commonLen); //從兩序列最後一個字元開始往前走,有一個字串Over就結束 while (aPos && bPos) { //兩序列最後一個元素相等,則同時往前走一步 if (len[aPos][bPos] == len[aPos - 1][bPos] + 1) { common[--k] = A[--aPos]; --bPos; } else if (len[aPos - 1][bPos] >= len[aPos][bPos - 1]) { --aPos; } else { --bPos; } } for (int i = 0; i < commonLen; i++) { cout << common[i]; } cout << endl; return commonLen; } int main(int argc, char const *argv[]) { string A = "ACCGGTCGAGATGCAG"; string B = "GTCGTTCGGAATGCAT"; cout << lcs(A, B); getchar(); return 0; }

演算法思路:

這裡寫圖片描述

這裡寫圖片描述

過程推演:

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述