蓝桥305查找最长的公共子序列

题目描述

查找最长的公共子序列

题目描述

实现一个算法查找两个字符串最长的公共子字符串。子字符串的介绍如下:

  • 子字符串是指字符串中任意个连续的字符组成的子序列。

输入描述

输入两行,每行一串字符串,长度均不超过 1000。

输出描述

输出一行,为最长公共子序列。

输入输出样例

示例

输入

ASDFGVCVMZKJ
OIKMASDFZCVM

输出

ASDF

运行限制

  • 最大运行时间:1s

  • 最大运行内存: 256M

题解 1

直接双重循环暴力方法

代码1

#include <algorithm>
#include <cstdint>
#include <iostream>
#include <limits>
#include <set>
#include <utility>
#include <vector>
#include <string>

using namespace std;



int main(){
    string str1;
    string str2;
    cin>>str1;
    cin>>str2;

    int s1=str1.size();
    int s2=str2.size();

    int ans=0,t=0,p=0;

    for(int i=0;i<s1;i++){
        for(int j=0;j<s2;j++){
            t=0;
            while(str1[i+t]==str2[j+t]){
                t++;
                if(t>ans){
                    p=j;
                }
            }
            ans=max(ans,t);
        }
    }
    cout<<str2.substr(p,ans);

    return 0;
}

题解2

 使用动态规划解法

状态转移方程:

设 dp[i][j] 表示字符串 X[1..i] 和 Y[1..j] 的最长公共子序列的长度。

1.如果 X[i] == Y[j],则 dp[i][j] = dp[i-1][j-1] + 1

2.如果 X[i] != Y[j],则 dp[i][j] = max(dp[i-1][j], dp[i][j-1])

3.初始化条件:对于所有的 i 和 jdp[i][0] = 0 和 dp[0][j] = 0

这三行等式构成了动态规划算法的核心,用于填充一个二维数组 dp,其中 dp[i][j] 存储了 X 的前 i 个字符和 Y 的前 j 个字符的最长公共子序列的长度。通过这种方式,我们可以避免重复计算子问题,从而有效地解决LCS问题。

代码2:

#include <iostream>
#include <vector>
#include <string>

using namespace std;

// 动态规划求解最长公共子序列问题
string longestCommonSubsequence(string text1, string text2) {
    int m = text1.size();
    int n = text2.size();
    vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));

    // 构建DP表
    for (int i = 1; i <= m; ++i) {
        for (int j = 1; j <= n; ++j) {
            if (text1[i - 1] == text2[j - 1]) {
                dp[i][j] = dp[i - 1][j - 1] + 1;
            } else {
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
            }
        }
    }

    // 从DP表中回溯找出LCS
    string lcs;
    int i = m, j = n;
    while (i > 0 && j > 0) {
        if (text1[i - 1] == text2[j - 1]) {
            lcs = text1[i - 1] + lcs;
            --i;
            --j;
        } else if (dp[i - 1][j] > dp[i][j - 1]) {
            --i;
        } else {
            --j;
        }
    }

    return lcs;
}

int main() {
    string str1, str2;
    cin >> str1 >> str2;
    cout << longestCommonSubsequence(str1, str2) << endl;
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值