最長共同子序列LCS—動態規劃實現
阿新 • • 發佈:2019-01-10
內容會持續更新,有錯誤的地方歡迎指正,謝謝!
前言:博主最近正在學習《演算法》這門專業課程,這是該課程的第三次上機題目,我把自己的解題方法分享給大家,歡迎討論!
題目:
描述並實現最長共同子序列動態規劃演算法,並顯示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;
}
演算法思路:
過程推演: