最长公共子序列问题 SDUT OJ 动态规划DP LCS问题

最长公共子序列问题

Description

给定两个序列 X={x1,x2,…,xm} 和 Y={y1,y2,…,yn},找出X和Y的最长公共子序列。

Input

输入数据有多组,每组有两行 ,每行为一个长度不超过500的字符串(输入全是大写英文字母(A,Z)),表示序列X和Y。

Output

每组输出一行,表示所求得的最长公共子序列的长度,若不存在公共子序列,则输出0。

Sample

Input 

ABCBDAB
BDCABA

Output 

4

 

解题思路:

最长公共子序列(Longest Common Sequence)

最长公共子序列问题不要求公共子序列部分连续,要求的是顺序相同的字符排列;最长公共子串问题要求的是一串相同的字符。

 

可参考:

1、最长公共子序列问题(动态规划) SDUT  https://blog.csdn.net/weixin_44143702/article/details/89429776

 2、https://www.cnblogs.com/wangkundentisy/p/9346376.html

 

#include <iostream> // cin cout
#include <cstring> //memset()
using namespace std;

int dp[505][505];///状态数组,可画出一个二维矩阵,代表dp[i][j]位置的最长公共子序列长度
string X, Y;
int LCS(int, int);///求解最长公共子序列的函数,两个参数为两个序列的长度
int main()
{
    cin >> X >> Y;
    int len_x = X.size();
    int len_y = Y.size();
    int common_len = LCS(len_x, len_y);///将函数返回的最长公共子序列长度保存
    cout << common_len << endl;
    return 0;
}
int LCS(int len_x, int len_y)
{///状态数组的长是从 0 到 len_x,宽是从 0 到 len_y
    ///初始化状态数组
    memset(dp, 0, sizeof(dp));
    for(int i = 0; i <= len_x; i++)
    {///初始化状态数组的第一列
        dp[i][0] = 0;
    }
    for(int j = 0; j <= len_y; j++)
    {///初始化状态数组的第一行
        dp[0][j] = 0;
    }
    ///从左到右,从上到下填充状态数组的值,即dp[i][j]位置的最长公共子序列长度
    for(int i = 1; i <= len_x; i++)
    {///遍历X序列从第一位到最后一位,即控制第i行
        for(int j = 1; j <= len_y; j++)
        {///遍历Y序列从第一位到最后一位,即控制第j列
            if(X[i - 1] == Y[j - 1])
            {///如果两序列尾部相等,则当前位置的dp[i][j]等于左上角dp值+1
                dp[i][j] = dp[i - 1][j - 1] + 1;
            }
            else
            {///如果两序列的末尾不相等,则取dp[i - 1][j]和dp[i][j - 1]的最大值
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
            }
        }
    }
    return dp[len_x][len_y];///返回序列X和Y整体的最长公共子序列的长度
}

 

参考:

1、动态规划经典——最长公共子序列问题 (LCS)和最长公共子串问题

https://www.cnblogs.com/wangkundentisy/p/9346376.html

 

2、最长公共子序列问题和动态规划

https://blog.csdn.net/kwinway/article/details/79183300

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值