【算法】力扣【动态规划,LCS】1143. 最长公共子序列

这篇具有很好参考价值的文章主要介绍了【算法】力扣【动态规划,LCS】1143. 最长公共子序列。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1143. 最长公共子序列


【算法】力扣【动态规划,LCS】1143. 最长公共子序列

题目描述

本文是对LCS这一动态规划模型的整理,以力扣平台上的算法题1143:最长公共子序列为模板题进行解析。

该题目要求计算两个字符串的最长公共子序列(Longest Common Subsequence,简称LCS)的长度。字符串的子序列是指在不改变字符顺序的情况下,通过删去某些字符后形成的新字符串。如果两个字符串没有公共子序列,返回0。

输入输出示例

示例 1:

  • 输入:text1 = “abcde”, text2 = “ace”
  • 输出:3
  • 解释: 最长公共子序列是 “ace” ,其长度为3。

示例 2:

  • 输入:text1 = “abc”, text2 = “abc”
  • 输出:3
  • 解释: 最长公共子序列是 “abc” ,其长度为3。

示例 3:

  • 输入:text1 = “abc”, text2 = “def”
  • 输出:0
  • 解释: 两个字符串没有公共子序列,返回0。

提示

  • 1 <= text1.length, text2.length <= 1000
  • text1 和 text2 仅由小写英文字符组成。

解题思路

为了解决该问题,我们使用动态规划的方法。定义状态dp(i, j)来表示text1[0...i-1]text2[0...j-1]这两个字符串的LCS长度。dp(len1, len2)将会是我们要求解的答案,其中len1len2分别是text1text2的长度。

状态转移方程

  • 如果text1[i - 1] == text2[j - 1],那么dp(i, j) = dp(i - 1, j - 1) + 1
  • 否则,dp(i, j) = max(dp(i - 1, j), dp(i, j - 1))

边界条件

i == 0j == 0时,即其中一个字符串长度为0,dp(i, j)必然为0。

代码解析

下面是使用C++实现的解决方案:

class Solution {
public:
    vector<vector<int>> memo;
    vector<vector<bool>> vis;
    string text1;
    string text2;
    
    int longestCommonSubsequence(string text1, string text2) {
        int len1 = text1.size(), len2 = text2.size();
        this->text1 = text1;
        this->text2 = text2;

        // 初始化记忆化数组
        memo = vector<vector<int>>(len1 + 1, vector<int>(len2 + 1, 0));
        vis = vector<vector<bool>>(len1 + 1, vector<bool>(len2 + 1, 0));
        
        // 从最大问题规模开始求解
        return dp(len1, len2);
    }

    // 主要的递归函数,用于解决子问题
    inline int dp(int i, int j) {
        // 边界条件处理
        if (i <= 0 || j <= 0) return 0;

        // 通过vis数组判断当前子问题是否已经解决过
        if (vis[i][j]) return memo[i][j];
        
        // 递归计算子问题
        int sub_solve_0 = dp(i - 1, j - 1);
        int sub_solve_1 = dp(i - 1, j);
        int sub_solve_2 = dp(i, j - 1);

        // 转移方程逻辑处理
        // 这里 i - 1 和 j - 1是因为i和j代表长度,
        // 减一后才是真实索引值。
        if (text1[i - 1] == text2[j - 1]) {
            memo[i][j] = sub_solve_0 + 1;
        } else {
            memo[i][j] = max(sub_solve_1, sub_solve_2);
        }
        
        // 标记当前子问题已解决并返回结果
        vis[i][j] = true;
        return memo[i][j];
    }
};

复杂度分析

  • 时间复杂度: O ( n × m ) O(n \times m) O(n×m),其中 n n n m m m分别是text1text2的长度。每对索引组合(i, j)最多只会被计算一次。
  • 空间复杂度: O ( n × m ) O(n \times m) O(n×m),用于存储所有子问题的解。

结论

动态规划提供了一种有效的方法,该方法通过分解为更小的子问题,并存储这些子问题的解来避免重复计算。这是动态规划的核心。使用动态规划求解LCS问题,我们通常使用选或不选子序列中的某一元素的思路来推导最长公共子序列中的元素组成,可以通过将两个串各自的长度作为问题规模看待,自顶向下地不断减小问题规模,再自底向上地利用子问题的解得到原问题的解。

注:LCS问题通常涉及2或者更多个串,但有时候也只会涉及一个串(比如1312. 让字符串成为回文串的最少插入次数),一般来说,对于这些串中的元素,从某种形式上可以按顺序(子序列是有顺序的)进行相互匹配(满足某种关系,比如相等…)。文章来源地址https://www.toymoban.com/news/detail-798509.html

到了这里,关于【算法】力扣【动态规划,LCS】1143. 最长公共子序列的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++ 动态规划经典案例解析之最长公共子序列(LCS)_窥探递归和动态规划的一致性

    动态规划处理字符相关案例中,求 最长公共子序列 以及求 最短编辑距离 ,算是经典中的经典案例。 讲解此类问题的算法在网上一抓应用一大把,即便如此,还是忍不住有写此文的想法。毕竟理解、看懂都不算是真正掌握,唯有瞧出其中玄机,能有自己独有的见解和不一样

    2024年02月13日
    浏览(38)
  • Day53【动态规划】1143.最长公共子序列、1035.不相交的线、53.最大子序和

    力扣题目链接/文章讲解 视频讲解 本题最大的难点还是定义 dp 数组  本题和718.最长重复子数组区别在于这里不要求是连续的了,但要有相对顺序 直接动态规划五部曲! 1、确定 dp 数组下标及值含义 dp[i][j]:取 text1 中下标 [0, i - 1] 的子字符串与 text2 中下标为 [0, j - 1] 的子字

    2024年02月14日
    浏览(40)
  • 代码随想录第53天|● 1143.最长公共子序列 ● 1035.不相交的线 ● 53. 最大子序和 动态规划

    dp[i][j]:长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串text2的最长公共子序列为dp[i][j] 通过pre记录前一个dp[j-1] 循环中记录cur为dp[i],循环结束后再更新pre=cur。 和最长公共子序列相同 注意pre和cur放置的位置 dp[i]:包括下标i(以nums[i]为结尾)的最大连续子序列和为dp[i

    2024年03月08日
    浏览(51)
  • 算法:动态规划——最长公共子序列

    动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。 与分治法不同的是,适合于用动态规划法求解的问题,经分解得到的子问题往往不是互相独立的。若用分治法解这类问题,则分解得到的

    2023年04月27日
    浏览(60)
  • 【算法-动态规划】最长公共子序列

    💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学习,不断总结,共同进步,活到老学到老 导航 檀越剑指大厂系列:全面总

    2024年01月23日
    浏览(47)
  • 【动态规划】最长公共子序列——算法设计与分析

    子序列是给定序列中在任意位置去掉任意多个字符后得到的结果。例如: 给定序列 X X X : X : A B C B D A B X:ABCBDAB X : A BCB D A B X X X 的子序列: X 1 : A B C B D A B X_1:ABCBDAB X 1 ​ : A BCB D A B X 2 : A B C B X_2:ABCB X 2 ​ : A BCB X 3 : A C B B X_3:ACBB X 3 ​ : A CBB 给定两个序列

    2024年02月05日
    浏览(55)
  • (Java) 算法——动态规划 最长公共子序列 图解

    遇到了用动态规划来求解最长公共子序列问题,算法这块儿比较薄弱,便想着在网上找现成的思路和代码,也算拾人牙慧,但有一点没想到,都已经22年了,关于LCS问题网上给出的答案如此一言难尽……,只有零散几篇对于 新手 来说比较友好,但也仅仅这样,好在自己花了点

    2023年04月08日
    浏览(47)
  • 【算法(四·三):动态规划思想——最长公共子序列问题】

    最长公共子序列(Longest Common Subsequence,简称LCS)问题是一种常见的字符串处理问题。它的**目标是找到两个或多个字符串中的最长公共子序列,这个子序列不需要是连续的,但字符在原始字符串中的相对顺序必须保持一致。**例如,考虑两个字符串\\\"ABCD\\\"和\\\"ACDF\\\",它们的最长公

    2024年04月13日
    浏览(49)
  • python数据结构与算法-动态规划(最长公共子序列)

    一个序列的子序列是在该序列中删去若干元素后得 到的序列。 例如:\\\"ABCD”和“BDF”都是“ABCDEFG”的子序列。 最长公共子序列(LCS) 问题: 给定两个序列X和Y,求X和Y长度最大的公共子字列。 例:X=\\\"ABBCBDE”Y=\\\"DBBCDB”LCS(XY)=\\\"BBCD\\\" 应用场景:字符串相似度比对 (1)问题思考 思考: 暴

    2024年02月08日
    浏览(52)
  • 算法分析:C语言实现动态规划之最长公共子序列

    最长公共子序列问题:          下面的简单问题说明了动态规划的基本原理。在字母表一∑上,分别给出两个长度为n和m的字符串A和B,确定在A和B中最长公共子序列的长度。这里,A = a₁a₂...an。的子序列是一个形式为a₁ka₂k...aik的字符串,其中每个i都在1和n之间,并且

    2023年04月21日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包