内容会持续更新,有错误的地方欢迎指正,谢谢!
前言:博主最近正在学习《算法》这门专业课程,这是该课程的第三次上机题目,我把自己的解题方法分享给大家,欢迎讨论!
题目:
描述并实现最长共同子序列动态规划算法,并显示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;
}
算法思路:
过程推演: