最长公共子序列

本文详细解析了求解两个字符串的最长公共子序列问题的动态规划算法,通过实例展示了算法的具体实现过程,并提供了完整的代码示例。适用于理解动态规划算法及解决相关字符串匹配问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://www.nowcoder.com/practice/4727c06b9ee9446cab2e859b4bb86bb8tpId=101&tqId=33099&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking

题目描述

给定两个字符串str1和str2,输出两个字符串的最长公共子序列。如过最长公共子序列为空,则输出-1。

输入描述:

输出包括两行,第一行代表字符串str1,第二行代表str2。(1≤length(str1),length(str2)≤5000)

输出描述:

输出一行,代表他们最长公共子序列。如果公共子序列的长度为空,则输出-1。

示例1

输入

1A2C3D4B56
B1D23CA45B6A

输出

123456

说明

"123456"和“12C4B6”都是最长公共子序列,任意输出一个。

备注:

时间复杂度O(n∗m),空间复杂度O(n∗m)。(n,m分别表示两个字符串长度)
//dp[i][j]的含义是s[0..i]与s[0..j]的最长公共子序列的长度
#include<bits/stdc++.h>
using namespace std;
int main(){
    string s1,s2;
    cin>>s1>>s2;
    int m=s1.size();
    int n=s2.size();
    vector<vector<int>> dp(m,vector<int>(n,0));
    if(s1[0]==s2[0]){
        dp[0][0]=1;
    }
    for(int i=1;i<m;i++){
        dp[i][0]=max(dp[i-1][0],(s1[i]==s2[0] ? 1 : 0));
    }
    for(int j=1;j<n;j++){
        dp[0][j]=max(dp[0][j-1],(s1[0]==s2[j] ? 1 : 0));
    }
    for(int i=1;i<m;i++){
        for(int j=1;j<n;j++){
            dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
            if(s1[i]==s2[j]){
                dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1);
            }
        }
    }
    string res="";
    int count=dp[m-1][n-1];
    int i=m-1,j=n-1;
    while(count>0){   //构建res序列
        if(i>0 && dp[i][j]==dp[i-1][j]){
            i--;
        }else if(j>0 && dp[i][j]==dp[i][j-1]){
            j--;
        }else{ //dp[i][j]==dp[i-1][j-1]+1 s1[i]==s2[j]
            res=s1[i]+res;
            i--;
            j--;
            count--;
        }
    }
    if(res.size()){
        cout<<res<<endl;
    }else{
        cout<<-1<<endl;
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值