E - 最长公共子序列问题

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

题解:

最长公共子序列(LCS)。
首先,从一个给定的串中删去(不一定连续地删去)0个或0个以上的字符,剩下地字符按原来顺序组成的串。例如:“ ”,“a”,“xb”,“aaa”,“bbb”,“xabb”,“xaaabbb”都是串“xaaabbb”的子序列。(例子中的串不包含引号。)
若s1[i] = s2[j]时,那么当前字母一定是某个公共子序列的尾字母,那么只要寻找s1与S2去掉当前字母的公共最长公共子序列+1(LCS(i-1, j-1)+1)就是当前两个字符串的最长公共子序列。
若s1[i] ≠ s2[j]时,那么当前最长公共子序列为max(LCS(i-1,j),LCS(i,j-1))。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define maxn 505
using namespace std;

/**
*s1 s2分别存储两个字符串。
*/
char s1[maxn],s2[maxn];
/**
*dp当前最大公共子序列
*/
int dp[maxn][maxn];

/**
*LCS()求最长公共子序列的函数
*i s1当前的游标。
*j s2当前的游标。
*/
int lcs(int i,int j){
    if(dp[i][j] != -1)
        return dp[i][j];
    //若有一方为0既当前有一个字符串长度为0.则公共子序列也为0;
    if(i==0||j==0){
        dp[i][j] = 0;
    }
    //若s1[i] = s2[j]时,那么当前字母一定是某个公共子序列的尾字母,
    //那么只要寻找(LCS(i-1, j-1)+1)就是当前两个字符串的最长公共子序列。
    else if(s1[i - 1] == s2[j - 1]){
            dp[i][j] = lcs(i - 1, j - 1) + 1;
        }
    //若s1[i] ≠ s2[j]时,那么当前最长公共子序列为
    //max(LCS(i-1,j),LCS(i,j-1))。
    else{
            dp[i][j] = max(lcs(i - 1, j), lcs(i, j - 1));
        }
    return dp[i][j];
}

int main()
{
    /**
    *l1字符串1的长度
    *l2字符串2的长度
    */
    int l1,l2;
    while(scanf("%s%s",s1,s2)!=EOF){
        memset(dp,-1,sizeof(dp));
        l1 = strlen(s1);
        l2 = strlen(s2);
        printf("%d\n",lcs(l1,l2));
    }
    return 0;
}
posted @   洛沐辰  阅读(524)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
历史上的今天:
2018-10-20 HDU-1114_Piggy-Bank
2018-10-20 HDU_1087-Super Jumping! Jumping! Jumping!
点击右上角即可分享
微信分享提示