[LeetCode每日一题]1143. 最长公共子序列
[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. 线性DP 1143. 最长公共子序列
最经典双串: 1143. 最长公共子序列 (LCS) https://leetcode-cn.com/problems/longest-common-subsequence/submissions/ ...
- LeetCode 1143 最长公共子序列
链接:https://leetcode-cn.com/problems/longest-common-subsequence 给定两个字符串 text1 和 text2,返回这两个字符串的最长公共子序 ...
- LeetCode第14题:最长公共前缀
题目描述 编写一个函数来查找字符串数组中的最长公共前缀. 如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["flower","flow ...
- 从最长公共子序列问题理解动态规划算法(DP)
一.动态规划(Dynamic Programming) 动态规划方法通常用于求解最优化问题.我们希望找到一个解使其取得最优值,而不是所有最优解,可能有多个解都达到最优值. 二.什么问题适合DP解法 如 ...
- Luogu 3402 最长公共子序列(二分,最长递增子序列)
Luogu 3402 最长公共子序列(二分,最长递增子序列) Description 经过长时间的摸索和练习,DJL终于学会了怎么求LCS.Johann感觉DJL孺子可教,就给他布置了一个课后作业: ...
- 【python】Leetcode每日一题-最长公共子序列
[python]Leetcode每日一题-最长公共子序列 [题目描述] 给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度.如果不存在 公共子序列 ,返回 0 . ...
- 【LeetCode每日一题 Day 5】5. 最长回文子串
大家好,我是编程熊,今天是LeetCode每日一题的第五天,一起学习LeetCode第五题<最长回文子串>. 题意 给你一个字符串 s,找到 s 中最长的回文子串. 示例 输入:s = & ...
- 每日一题-——最长公共子序列(LCS)与最长公共子串
最长公共子序列(LCS) 思路: 代码: def LCS(string1,string2): len1 = len(string1) len2 = len(string2) res = [[0 for ...
- 【js】Leetcode每日一题-完成所有工作的最短时间
[js]Leetcode每日一题-完成所有工作的最短时间 [题目描述] 给你一个整数数组 jobs ,其中 jobs[i] 是完成第 i 项工作要花费的时间. 请你将这些工作分配给 k 位工人.所有工 ...
随机推荐
- Learn Python the Hard Way,ex37-1
本练习为复习python的符号和关键字 关键字有: #and or False True print(1==0 and 2==0, 1==0 or 2==0) print(False) print(T ...
- idea添加本地文件约束(DTD)
当我们做 xml 文件配置的时候,需要对其进行约束的配置 例如: hibernate 如果我们在联网的情况下是可以不添加配置文件约束的,红框内的 URL 会自动帮我们从网络上加载约束文件,但是没有网络 ...
- string与bson.ObjectId之间格式转换
string转bson.ObjectId bson.ObjectIdHex(string) bson.ObjectId转string日后再补
- js toFixed
为什么(2.55).toFixed(1)等于2.5? 上次遇到了一个奇怪的问题:JS的(2.55).toFixed(1)输出是2.5,而不是四舍五入的2.6,这是为什么呢? 进一步观察: 发现,并不是 ...
- git提交本地文件到远程仓库及参与的项目仓库
1.git提交本地文件到组织 1.先再组织中建立个用于存放文件的仓库建然后复制仓库地址: 2.进入要上传的文件的根目录下右击 git Bash 进入git控制台,我要上传的文件如下: 3.进入后: 1 ...
- Android | 玩转AppBarLayout,设置scrollFlags滑动属性详解
CoordinatorLayout与AppBarLayout的配合使用,在之前的文章中我们也经常使用,主要是专门用来打造各种炫酷的效果. 有童鞋看了之前的文章反馈对AppBarLayout中的scro ...
- clickhouse 亿级数据性能测试
clickhouse 在数据分析技术领域早已声名远扬,如果还不知道可以 点这里 了解下. 最近由于项目需求使用到了 clickhouse 做分析数据库,于是用测试环境做了一个单表 6 亿数据量的性能测 ...
- 攻防世界 reverse babymips
babymips XCTF 4th-QCTF-2018 mips,ida中想要反编译的化需要安装插件,这题并不复杂直接看mips汇编也没什么难度,这里我用了ghidra,直接可以查看反编译. 1 ...
- node_exporter自定义监控
背景 我们在使用Zabbix的时候,可以自己写自定义脚本.在使用Promethues的时候,有很多的exporter,但是有一些特殊的情况没有,比如,我需要监控进程一启动就告警,但是进程没启动,是使用 ...
- 在 .NET Core 中使用 ViewConfig 调试配置
介绍 .NET Core 中的配置包含了多个配置提供程序,包括了 appsettings.json,环境变量,命令行参数等,还有一些扩展的自定义提供程序,比如说 ApolloConfig,AgileC ...