例如,X=“ABCBDAB”,Y=“BCDB”是X的一个子序列。给定两个序列A和B,称序列Z是A和B的公共子序列,是指Z同是A和B的子序列。编写算法求一直两序列A和B的最长公共子序列。

分析:
v[i][j]存储序列“a0,a1,…,ai-1”, “b0,b1,…,bj-1”的最长公共子序列的长度。
则v[i][j]的计算如下:
(1). v[i][j] = 0;
(2). v[i][j] = v[i-1][j-1]+1, 如果a[i-1] = b[j-1]
(3). v[i][j] = max(v[i-1][j],v[i][j-1]),如果a[i-1] != b[j-1]

C++代码:

解法一(递归法):

#include <iostream>
#include <vector>
#include <string>
using namespace std;

//在计算最优值,
int lcs_len(const string &s1,const string &s2, vector<vector<int>> &v, int i, int j)
{
    if (i == 0 || j == 0)
    {
        v[i][j] = 0;
    }
    else
    {
        //不保证会求v中的每个元素
        if (s1[i-1] == s2[j-1])
        {
            v[i][j] = lcs_len(s1,s2,v,i-1,j-1) + 1;
        }
        else 
        {
            int L1 = lcs_len(s1,s2,v,i-1,j);
            int L2 = lcs_len(s1,s2,v,i,j-1);
            if (L1 >= L2)
            {
                v[i][j] = L1;
            }
            else
                v[i][j] = L2;
        }
    }
    return v[i][j];
}

//构造最长公共子序列,k为公共子序列长度
void buile_lcs(const string &s1,const string &s2,const vector<vector<int>> &v, int i, int j, string &sub/*, int k*/)
{
    if (i == 0 || j == 0)
    {
        return ;
    }
    else
    {

        if (v[i][j] == v[i][j-1])
        {
            buile_lcs(s1,s2,v,i,j-1,sub);
        } 
        else if (v[i][j] == v[i-1][j])
        {
            buile_lcs(s1,s2,v,i-1,j,sub);
        }
        else
        {
            sub = s1[i-1] + sub;
            buile_lcs(s1,s2,v,i-1,j-1,sub);
        }
    }
}

int main()
{
    string s1,s2;
    cin>>s1>>s2;
    int i = s1.length();
    int j = s2.length();
    vector<vector<int>> v;
    vector<int> tmp(j+1,0);
    for (int k=0;k<=i;++k)
    {
        v.push_back(tmp);
    }
    lcs_len(s1,s2,v,i,j);
    string sub = "";
    buile_lcs(s1,s2,v,i,j,sub);
    /*for (vector<vector<int>>::iterator ita=v.begin();ita != v.end();++ita)
    {
        for (vector<int>::iterator itb=ita->begin();itb!= ita->end();++itb)
        {
            cout<<*itb<<' ';
        }
        cout<<endl;
    }*/
    cout<<sub<<endl;
    return 0;
}

解法二:

#include <iostream>
#include <vector>
#include <string>
using namespace std;

//在计算最优值
void lcs_len(const string &s1,const string &s2, vector<vector<int>> &v)
{
    int len1 = s1.length();
    int len2 = s2.length();
    vector<int> tmp(len2+1,0);
//  v.resize(len1+1);
    for (int i=0;i<len1+1;++i)
    {
        v.push_back(tmp);
    }
    /*cout<<v.size()<<endl;*/
    for (int i=1;i<len1+1;++i)
    {
        for (int j=1;j<len2+1;++j)
        {
            if (s1[i-1] == s2[j-1])
            {
                v[i][j] = 1+v[i-1][j-1];
            }
            else if (v[i-1][j] >= v[i][j-1])
            {
                v[i][j] = v[i-1][j];
            } 
            else
            {
                v[i][j] = v[i][j-1];
            }
        }
    }
}

//构造最长公共子序列,k为公共子序列长度
string buile_lcs(const string &s1,const string &s2,const vector<vector<int>> &v)
{
    string com_subseq="";
    int len1 = s1.length();
    int len2 = s2.length();
    int i = len1;
    int j = len2;
    int k = v[len1][len2];
    while (k)
    {
        if (v[i][j] == v[i][j-1])
        {
            --j;
        }
        else if (v[i][j] == v[i-1][j])
        {
            --i;
        }
        else
        {
            com_subseq = s1[i-1]+com_subseq;
            --i;
            --j;
            --k;
        }
    }
    return com_subseq;
}

int main()
{
    string s1,s2;
    cin>>s1>>s2;
    vector<vector<int>> v;
    lcs_len(s1, s2,v);
    /*for (vector<vector<int>>::iterator ita = v.begin();ita != v.end();++ita)
    {
        for (vector<int>::iterator itb = ita->begin();itb != ita->end();++itb)
        {
            cout<<*itb<<' ';
        }
        cout<<endl;
    }
    cout<<endl;*/
    cout<<buile_lcs(s1,s2,v);
    return 0;
}

运行结果:
输入:ABCBDAB BDCABA
输出:BDAB

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值