[LeetCode每日一题]1143. 最长公共子序列

问题

给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0 。

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。

例如,"ace" 是 "abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。
两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。 示例 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 仅由小写英文字符组成。

简单的动态规划,z大神秒杀的那种,本菜鸡瑟瑟发抖。

解题思路

求两个数组或者字符串的最长公共子序列问题,肯定是要用动态规划的。

首先,区分两个概念:子序列可以是不连续的;子数组(子字符串)需要是连续的;

另外,动态规划也是有套路的:单个数组或者字符串要用动态规划时,可以把动态规划 dp[i] 定义为 nums[0:i] 中想要求的结果;当两个数组或者字符串要用动态规划时,可以把动态规划定义成两维的 dp[i][j] ,其含义是在 A[0:i] 与 B[0:j] 之间匹配得到的想要的结果。

1.状态定义

比如对于本题而言,可以定义 dp[i][j]表示 text1[0:i-1] 和 text2[0:j-1] 的最长公共子序列。 (注:text1[0:i-1] 表示的是 text1 的 第 0 个元素到第 i - 1 个元素,两端都包含)

之所以 dp[i][j] 的定义不是 text1[0:i] 和 text2[0:j] ,是为了方便当 i = 0 或者 j = 0 的时候,dp[i][j]表示为空字符串和另外一个字符串的匹配,这样 dp[i][j] 可以初始化为 0.

2.状态转移方程

知道状态定义之后,我们开始写状态转移方程。

当 text1[i - 1] == text2[j - 1] 时,说明两个子字符串的最后一位相等,所以最长公共子序列又增加了 1,所以 dp[i][j] = dp[i - 1][j - 1] + 1;举个例子,比如对于 ac 和 bc 而言,他们的最长公共子序列的长度等于 a 和 c 的最长公共子序列长度 0 + 1 = 1。

当 text1[i - 1] != text2[j - 1] 时,说明两个子字符串的最后一位不相等,那么此时的状态 dp[i][j] 应该是 dp[i - 1][j] 和 dp[i][j - 1] 的最大值。举个例子,比如对于 ace 和 bc 而言,他们的最长公共子序列的长度等于 ① ace 和 b 的最长公共子序列长度0 与 ② ac 和 bc 的最长公共子序列长度1 的最大值,即 1。

综上状态转移方程为:

dp[i][j] = dp[i - 1][j - 1] + 1dp[i][j]=dp[i−1][j−1]+1, 当 text1[i - 1] == text2[j - 1];text1[i−1]==text2[j−1];

dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])dp[i][j]=max(dp[i−1][j],dp[i][j−1]), 当 text1[i - 1] != text2[j - 1]text1[i−1]!=text2[j−1]

3.状态的初始化

初始化就是要看当 i = 0 与 j = 0 时, dp[i][j] 应该取值为多少。

当 i = 0 时,dp[0][j] 表示的是text1中取空字符串 跟text2的最长公共子序列,结果肯定为 0.

当 j = 0 时,dp[i][0] 表示的是text2中取空字符串 跟text1的最长公共子序列,结果肯定为 0.

综上,当 i = 0 或者 j = 0 时,dp[i][j] 初始化为 0.

4.遍历方向与范围

由于 dp[i][j] 依赖与 dp[i - 1][j - 1] , dp[i - 1][j], dp[i][j - 1],所以i和j的遍历顺序肯定是从小到大的。

另外,由于当 ii 和 jj 取值为 0 的时候,dp[i][j] = 0,而 dp 数组本身初始化就是为 0,所以,直接让 i 和 j 从 1 开始遍历。遍历的结束应该是字符串的长度为 len(text1) 和 len(text2)。

5.最终返回结果

由于 dp[i][j] 的含义是 text1[0:i-1] 和 text2[0:j-1] 的最长公共子序列。我们最终希望求的是 text1 和 text2 的最长公共子序列。所以需要返回的结果是 i = len(text1) 并且 j = len(text2) 时的 dp[len(text1)][len(text2)]。

代码

经过上面的分析,我们可以得到下面的代码。

#include<bits/stdc++.h>
using namespace std;
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
int m = text1.length(), n = text2.length();
vector<vector<int>> dp(m + 1, vector<int>(n + 1));
for (int i = 1; i <= m; i++) {
char c = text1.at(i - 1);
for (int j = 1; j <= n; j++) {
char b = text2.at(j - 1);
if (c == b) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
cout << dp[m][n] << endl;
return dp[m][n];
}
}; int main() {
Solution s;
string text1, text2;
text1 = "abcde", text2 = "ace";
s.longestCommonSubsequence(text1, text2);
return 0;
}

[LeetCode每日一题]1143. 最长公共子序列的更多相关文章

  1. 1. 线性DP 1143. 最长公共子序列

    最经典双串: 1143. 最长公共子序列 (LCS)  https://leetcode-cn.com/problems/longest-common-subsequence/submissions/ ...

  2. LeetCode 1143 最长公共子序列

    链接:https://leetcode-cn.com/problems/longest-common-subsequence 给定两个字符串 text1 和 text2,返回这两个字符串的最长公共子序 ...

  3. LeetCode第14题:最长公共前缀

    题目描述 编写一个函数来查找字符串数组中的最长公共前缀. 如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["flower","flow ...

  4. 从最长公共子序列问题理解动态规划算法(DP)

    一.动态规划(Dynamic Programming) 动态规划方法通常用于求解最优化问题.我们希望找到一个解使其取得最优值,而不是所有最优解,可能有多个解都达到最优值. 二.什么问题适合DP解法 如 ...

  5. Luogu 3402 最长公共子序列(二分,最长递增子序列)

    Luogu 3402 最长公共子序列(二分,最长递增子序列) Description 经过长时间的摸索和练习,DJL终于学会了怎么求LCS.Johann感觉DJL孺子可教,就给他布置了一个课后作业: ...

  6. 【python】Leetcode每日一题-最长公共子序列

    [python]Leetcode每日一题-最长公共子序列 [题目描述] 给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度.如果不存在 公共子序列 ,返回 0 . ...

  7. 【LeetCode每日一题 Day 5】5. 最长回文子串

    大家好,我是编程熊,今天是LeetCode每日一题的第五天,一起学习LeetCode第五题<最长回文子串>. 题意 给你一个字符串 s,找到 s 中最长的回文子串. 示例 输入:s = & ...

  8. 每日一题-——最长公共子序列(LCS)与最长公共子串

    最长公共子序列(LCS) 思路: 代码: def LCS(string1,string2): len1 = len(string1) len2 = len(string2) res = [[0 for ...

  9. 【js】Leetcode每日一题-完成所有工作的最短时间

    [js]Leetcode每日一题-完成所有工作的最短时间 [题目描述] 给你一个整数数组 jobs ,其中 jobs[i] 是完成第 i 项工作要花费的时间. 请你将这些工作分配给 k 位工人.所有工 ...

随机推荐

  1. HTML基础速览

    HTML概述 HTML ,CSS , JavaScript, JQuery, Vue 的关系 HTML可以写一个简单的前端,但是很丑,所以需要CSS对HTML进行美化 HTML是静态的.JavaScr ...

  2. Serverless Wordpress 系列建站教程(三)

    从前面两篇教程文章里,我们可以了解到 Serverless WordPress 的低门槛部署,免运维等功能优势.而建站场景中,开发者关注的另一个重点则是成本问题,Serverless 架构究竟如何计费 ...

  3. C# 基础 - 日志捕获二使用 log4net

    引入 log4net.dll 项目->添加->新建项->应用程序配置文件,命名为 log4net.config,并把属性的复制到输出目录设置为 如果较新则复制,后续客户端需要读取在 ...

  4. 单元测试 - SpringBoot2+Mockito实战

    单元测试 - SpringBoot2+Mockito实战 在真实的开发中,我们通常是使用SpringBoot的,目前SpringBoot是v2.4.x的版本(SpringBoot 2.2.2.RELE ...

  5. SpringMVC源码分析和启动流程

    https://yq.aliyun.com/articles/707995 在Spring的web容器启动时会去读取web.xml文件,相关启动顺序为:<context-param> -- ...

  6. (2)MySQL进阶篇SQL优化(show status、explain分析)

    1.概述 在应用系统开发过程中,由于初期数据量小,开发人员写SQL语句时更重视功能上的实现,但是当应用系统正式上线后,随着生产数据量的急剧增长,很多SQL语句开始逐渐显露出性能问题,对生产环境的影响也 ...

  7. P1047_校门外的树(JAVA语言)

    题目描述 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米. 我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置: 数轴上的每个整数点,即0,1,2,-,L都种 ...

  8. Java 给PPT添加动画效果(预设动画/自定义动画)

    PPT幻灯片中对形状可设置动画效果,常见的动画效果为内置的固定类型,即动画效果和路径是预先设定好的固定模板,但在设计动画效果时,用户也可以按照自己的喜好自定义动画动作路径.下面,通过Java后端程序代 ...

  9. 一键部署etcd集群管理脚本

    一.编写脚本 1 #!/bin/sh 2 # 安装 3 # ./run.sh etcd03 etcd01=http://192.168.2.44:2380,etcd02=http://192.168. ...

  10. HTML5和CSS3提高

    一.HTML5的新特性 HTML5 的新增特性主要是针对于以前的不足,增加了一些新的标签.新的表单和新的表单属性等. 这些新特性都有兼容性问题,基本是 IE9+ 以上版本的浏览器才支持,如果不考虑兼容 ...