最长共同子序列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;
}

算法思路:

这里写图片描述

这里写图片描述

过程推演:

这里写图片描述

这里写图片描述

这里写图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值