前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >动态规划问题-LeetCode 5 (经典DP问题、LCS问题)

动态规划问题-LeetCode 5 (经典DP问题、LCS问题)

作者头像
算法工程师之路
发布于 2019-09-17 10:24:27
发布于 2019-09-17 10:24:27
2.3K00
代码可运行
举报
运行总次数:0
代码可运行
作者:TeddyZhang,公众号:算法工程师之路

DP基础问题:LeetCode #5

1

编程题

【LeetCode #5】最长回文子串

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

示例 1: 输入: "babad" 输出: "bab" 注意: "aba" 也是一个有效答案。 示例 2: 输入: "cbbd" 输出: "bb"

解题思路:

前两天我们讲解了"中心拓展法"来解这道题目,今天我们使用动态规划的方法来写这道题目,首先我们要寻找一个递推式如下: 我们将f[i][j]表述为从j到i的子串为回文串,j <= i,此时dp的矩阵为左下三角! 如果a[i]==a[j]且f[i-1][j+1]=true, 那么f[i][j]也为true。

需要注意一点:当i-j < 2时,如果s[i]=s[j],那么f[i][j]必为true,即单个字符或者两个相邻相同字符为回文子串。

C++代码为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
public:
    string longestPalindrome(string s) {
        int slen = s.length();
        if(slen == ) return "";
        string res = "";
        vector<vector<bool>> f(slen, vector<bool>(slen, false));
        int maxlen = ;
        int curlen = ;

        for(int i = ;i < slen; i++){
            for(int j = ;j <= i; j++){   // f[0][0]=true, 一定成立
                if((s[i] == s[j]) && ((i-j < ) || (i >  && f[i-1][j+]))){
                    f[i][j] = true;
                    curlen = i - j + ;
                    if(curlen > maxlen){
                        maxlen = curlen;
                        res = s.substr(j, curlen);
                    }
                }
            }
        }
        return res;
    }
};

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/longest-palindromic-substring

【经典动态规划】最长公共子序列

给定两个字符串A和B,长度分别为m和n,要求找出它们最长的公共子序列,并返回其长度。 A = "Hello World" B = "loop" 则A与B的最长公共子序列为"loo", 返回最大长度为3.

注意:公共子序列不要求连续,而公共子串要求连续!

解题思路:

我们首先定义动态规划矩阵dp[i][j]为字符串A的第一个字符到第i个字符以及字符串B的第一个字符到第j个字符的最长公共子序列。比如A为"cake", B为"cat",则dp[2][3]表示"ca"和"cat"之间的最长公共子序列!其中dp[0][2]表示""和"ca"的最长公共子序列,为零! 因此我们可以得到递推式为:

其中,dp[i][0] = 0, dp[0][j] = 0.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class LCS
{
public:
    int findLCS(string A, int n, string B, int m)
    {
        if(n ==  || m == )//特殊输入
            return ;
        int dp[n + ][m + ];//定义状态数组
        for(int i =  ; i <= n; i++)//初始状态
            dp[i][] = ;
        for(int i = ; i <= m; i++)
            dp[][i] = ;
        for(int i = ; i <= n; i++)
            for(int j = ; j<= m; j++)
            {
                if(A[i - ] == B[j - ])//判断A的第i个字符和B的第j个字符是否相同
                    dp[i][j] = dp[i -1][j - ] + ;
                else
                    dp[i][j] = max(dp[i - ][j],dp[i][j - ]);
            }
            return dp[n][m];//最终的返回结果就是dp[n][m]
    }
};

【经典动态规划】最长公共子串

给定两个字符串A和B,长度分别为m和n,要求找出它们最长的公共子串,并返回其长度。例如: A = "HelloWorld" B = "loop" 则A与B的最长公共子串为 "lo",返回的长度为2。

解题思路:

最长公共子串的问题不同于最长公共子序列,由于子串的连续的,而子序列不一定连续。在上一个子序列中dp[i][j]是非减的,因此最后返回最大公共子序列时,返回的是dp[n][m]。而在最大子串问题中,dp[i][j]可能小于dp[i-1][j-1],因此需要一个res来保存更新最大值。

通俗考虑,在两个子串中寻找,假设a[i]==b[j]了,那么从i和j向后走,res会一直更新变大,一旦遇到不相等时,则dp[i][j]清零,寻找下一个重复的子串。因此其递推式为:

其中dp[i][0] = 0, dp[0][j] = 0;

C++代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class LongestSubstring {
public:
    int findLongest(string A, int n, string B, int m) {
         if(n ==  || m == )
            return ;
        int rs = ;
        int dp[n + ][m + ];
        for(int i =  ; i <= n; i++)//初始状态
            dp[i][] = ;
        for(int i = ; i <= m; i++)
            dp[][i] = ;
        for(int i = ; i <= n; i++)
            for(int j = ; j<= m; j++)
            {
                if(A[i - ] == B[j - ])
                {
                    dp[i][j] = dp[i -1][j - ] + ;
                    rs = max(rs,dp[i][j]);//每次更新记录最大值
                }

                else//不相等的情况
                    dp[i][j] = ;
            }
            return rs;//返回的结果为rs
    }
};

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 算法工程师之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
搞定大厂算法面试之leetcode精讲20.字符串
方法1.截取字符串,循环字符串,遇到#就截掉最后一个字符,循环完毕之后,最后比较两个去除掉#退格之后的字符串是否相等,时间复杂度O(m+n),m、n是两个字符串的长度。空间复杂度O(1)
全栈潇晨
2021/12/04
7210
LCS/最长公共子序列/最长公共子串 实现 Python/Java
http://blog.csdn.net/u012102306/article/details/53184446 http://blog.csdn.net/hrn1216/article/details/51534607
蛮三刀酱
2019/03/26
1K0
LCS/最长公共子序列/最长公共子串 实现 Python/Java
【力扣刷题】5. 最长回文子串
根据回文串的定义,正着和反着读一样,那我们是不是把原来的字符串倒置了,然后找最长的公共子串就可以了。例如 S = "caba" ,S = "abac",最长公共子串是 "aba",所以原字符串的最长回文串就是 "aba"。
jayjay
2022/11/02
2310
【力扣刷题】5. 最长回文子串
poj 1159 Palindrome(最长公共子串)
MaxLen(i, j) = 0 //两个空串的最长公共子序列长度当然是0
xindoo
2021/01/22
4390
poj 1159 Palindrome(最长公共子串)
BAT面试算法进阶(5)- 最长回文子串(方法一)
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
iOSSir
2023/03/19
2500
BAT面试算法进阶(5)- 最长回文子串(方法一)
golang刷leetcode 动态规划(13) 最长公共子序列
一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。
golangLeetcode
2022/08/02
4580
Q5 Longest Palindromic Substring
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000. Example: Input: "babad" Output: "bab" Note: "aba" is also a valid answer. Example: Input: "cbbd" Output: "bb" 解题思路: 最长回文子串,一句话总结:暴力 O(n^3),
echobingo
2018/04/25
7610
动态规划-各种子序列问题集合
当i=1,则dp[1]=2;因为dp[i]会和之前每一个元素j代替进行比对,当a[i]<a[j],并且dp[j]+1>dp[i].则dp[i]=dp[j]+1
十四君
2019/11/24
4740
LeetCode 5. Longest Palindromic Substring分析
判断一个字符串是不是回文串,可以用动态规划方法 dp[i][j]:表示i到j的字符串,是不是回文串,是就为true,不是就为false 那么当s[i] == s[j]的时候,dp[i][j] = dp[i+1][j-1],这是根据回文串的特点,比较容易理解的,比如我们知道bab是回文串,如果a = a,那么ababa也就是回文串! 所以我们可以用动态规划法求出最长回文串,然后也知道了他的起始位置,i和j,所以就比较容易求解了,唯一注意的问题是,我们得倒着求,而不能跟往常一样顺着求解,因为状态转移方程的依赖关系,是倒着依赖的。
desperate633
2018/08/22
2990
POJ 1159 Palindrome 最长公共子序列的问题
Description A palindrome is a symmetrical string, that is, a string read identically from left to right as well as from right to left. You are to write a program which, given a string, determines the minimal number of characters to be inserted into the string in order to obtain a palindrome.
谙忆
2021/01/19
3130
【算法】动态规划:回文子串问题、两个数组的dp
定义 dp[i][j] 表示 [i, j] 区间内的字符串是否是回文子串,i <= j,要特别注意填表顺序。
_小羊_
2025/03/27
1220
【算法】动态规划:回文子串问题、两个数组的dp
最长公共子串 / 子序列
本文记录寻找两个字符串最长公共子串和子序列的方法。 名词区别 最长公共子串(Longest Common Substring)与最长公共子序列(Longest Common Subsequence)的区别: 子串要求在原字符串中是连续的,而子序列则只需保持相对顺序,并不要求连续。 最长公共子串 是指两个字符串中最长连续相同的子串长度。 例如:str1=“1AB2345CD”,str2=”12345EF”,则str1,str2的最长公共子串为2345。 动态规划 如果 str1 的长度为
为为为什么
2022/08/10
4.7K0
最长公共子串 / 子序列
最长公共子串/序列问题
给定两个字符串 text1 和 text2,返回这两个字符串的最长公共子序列的长度。
你的益达
2020/08/17
6750
动态规划之最长回文子串
还是先看暴力解法:枚举子串的两个端点i和j,判断在[i, j]区间内的子串是否回文。从复杂度上来看,枚举端点需要0(n2),判断回文需要0(n),因此总复杂度是O(n3)。终于碰到一个暴力复杂度不是指数级别的问题了!但是O(n)的复杂度在n很大的情况依旧不够看。 可能会有读者想把这个问题转换为最长公共子序列(LCS) 问题来求解:把字符串S倒过来变成字符串T,然后对S和T进行LCS模型求解,得到的结果就是需要的答案。而事实上这种做法是错误的,因为一旦S中同时存在一个子串和它的倒序,那么答案就会出错。例如字符串S= “ABCDZJUDCBA”,将其倒过来之后会变成T = “ABCDUJZDCBA”,这样得到最长公共子串为”ABCD”,长度为4,而事实上S的最长回文子串长度为1。因此这样的做法是不行的。 动态规划解决 令dp[i][j]表示S[i]至S[j]所表示的子串是否是回文子串,是则为1,不是为0。这样根据S[i]是否等于S[j],可以把转移情况分为两类: ①若S[i]=S[j],那么只要S[i+1]和S[j-1]是回文子串,S[i+1]至S[j-1]就是回文子串;如果S[i+1]至S[j-1]不是回文子串,则S[i]至S[j]一定不是回文子串。 ②若S[i]!=S[j],那S[i]至S[j]一定不是回文子串。 由此可以写出状态转移方程
全栈程序员站长
2022/08/10
4790
动态规划之最长回文子串
Leetcode【712、746、877】
读完题目后发现:把两个字符串中多余的字符删除后,最后留下的字符串是两个字符串的最长公共子序列。因此这道题可以像最长公共子序列一样,采用动态规划的思想解决:常考的经典算法--最长公共子序列(LCS)与最长公共子串(DP)。
echobingo
2019/06/14
4150
Leetcode【712、746、877】
【LeetCode题解-005】Longest Palindrome Substring
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
周三不加班
2019/09/04
4600
【LeetCode题解-005】Longest Palindrome Substring
浅谈我对动态规划的一点理解---大家准备好小板凳,我要开始吹牛皮了~~~
前言 作为一个退役狗跟大家扯这些东西,感觉确实有点。。。但是,针对网上没有一篇文章能够很详细的把动态规划问题说明的很清楚,我决定还是拿出我的全部家当,来跟大家分享我对动态规划的理解,我会尽可能的把所遇到的动态规划的问题都涵盖进去,博主退役多年,可能有些地方会讲的不完善,还望大家多多贡献出自己的宝贵建议,共同进步~~~ 概念 首先我们得知道动态规划是什么东东,百度百科上是这么说的,动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数
Angel_Kitty
2018/04/08
4.6K0
浅谈我对动态规划的一点理解---大家准备好小板凳,我要开始吹牛皮了~~~
算法:动态规划
上面是一个按照时间段发生的任务a,b,c,d,e,f,g,h,有的任务之间会有时间重叠。定义:
用户3578099
2022/04/18
1.7K0
算法:动态规划
(Leetcode 2021 刷题计划) 1143. 最长公共子序列
给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0 。
windism
2021/04/05
9610
掌握套路,你也会用动态规划
动态规划并不是一种具体的算法,而是一种思想,个人觉得就是缓存+枚举,把求解的问题分成许多阶段或者多个子问题,然后按顺序求解各子问题。前一子问题的解为后一子问题提供了有用的信息。在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。依次解决各子问题,最后一个子问题就是初始问题的解。
Java识堂
2020/07/13
4850
相关推荐
搞定大厂算法面试之leetcode精讲20.字符串
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验