LCS的理解AND实现

课程:THU 数据结构与算法 第一章 绪论 第六节 动态规划
代码参考:https://songlee24.github.io/2014/11/29/print-all-LCS/
自己的实现+注释 107行(包括注释和没什么用的换行)

By 2018-05-25

 

尽可能的把全局变量局部化(习惯)

 

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

vector<vector<int>> table;//LCS路径表

/*最大子序列长度计算
 构造LCS路径表*/
int LCS(string a, string b);

/*追踪所有子序列字符串并一起扔到set里
  str为每个最大公共子序列*/
voidTraceBack(string a, string b, string str, set<string>& LCSset);

int main(int argc, char* argv[])
{
    string x, y, empty_str;
    set<string> LCS_SET;
    cin>>  x >> y;
    cout<< "最大公共子序列的长度是" << LCS(x, y) << endl;

    TraceBack(x,y, empty_str, LCS_SET);
    //输出
    set<string>::iterator beg =LCS_SET.begin();
    for (; beg != LCS_SET.end(); ++beg)
        cout<< *beg << endl;

    system("pause");
    return 0;
}

int LCS(string a, string b)
{
    //表的大小为 a长+1*b长+1
    table= vector<vector<int>>(a.size() + 1, vector<int>(b.size() + 1));
    //构造路径表
    for (int i = 0; i < a.size() + 1; i++)

        for (int j = 0; j < b.size() + 1; j++)
        {
            if (i == 0 || j == 0)//第一行第一列设0
                table[i][j] = 0;
            else if (a[i - 1] == b[j - 1])//比对成功+1
                table[i][j] = table[i - 1][j - 1] + 1;
            else//比对失败继承较大的
                table[i][j] = max(table[i - 1][j], table[i][j - 1]);
        }
    //输出表
    for (int i = 0; i < a.size() + 1; ++i)
    {
        for (int j = 0; j < b.size() + 1; ++j)
        {
            cout<< table[i][j] << " ";
        }
        cout<< endl;
    }
    //返回右下角的值(最大长度)
    return table[a.size()][b.size()];
}

//字符串逆序
void Revense(string & str)
{
    int low = 0, high = str.length() - 1;
    char temp;
    while (low < high)
    {
        temp= str[low];
        str[low] = str[high];
        str[high] = temp;
        low++;high--;
    }
}

void TraceBack(string a, string b, string str, set<string>& LCSset)
{
    int a_length = a.size(), b_length = b.size();
    //用长度递减循环查表(从右下到左上)
    while(a_length > 0&& b_length > 0)
    {
        if (a[a_length - 1] == b[b_length - 1])//相同直接插入
        {
            str.push_back(a[a_length - 1]);
            a_length--;
            b_length--;
        }
        else
        {
            //若不相同
            //如果上面的数值大就往上面走
            if (table[a_length - 1][b_length] > table[a_length][b_length - 1])
                a_length--;
            //如果左边的数值大就往左边走
            else if (table[a_length - 1][b_length] < table[a_length][b_length - 1])
                b_length--;
            //相同的情况下就两边都走
            else
            {
                TraceBack(a.substr(0, a_length- 1), b.substr(0,b_length), str, LCSset);//向上
                TraceBack(a.substr(0,a_length), b.substr(0,b_length-1), str, LCSset);//向左
                return;
            }
        }
    }
    Revense(str);//逆序str(插入的是逆序,返回来
    LCSset.insert(str);//每个子序列都放入set中
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值