首页 > 编程语言 >代码随想录算法训练营day46| 647. 回文子串 516.最长回文子序列

代码随想录算法训练营day46| 647. 回文子串 516.最长回文子序列

时间:2024-11-14 21:20:55浏览次数:1  
标签:子串 随想录 len range 647 序列 dp 回文

学习资料:https://programmercarl.com/0647.回文子串.html#算法公开课

动态规划最后一部分:回文字符串
子串是从原字符串中连续截取的;子序列可以是从原字符串中不连续提取出元素构成的

学习记录:
647.回文子串(难构造dp数组,dp数组是从原字符串截取[i,j]范围的片段是否是回文字符串,布尔变量;这样构造才能推出递推公式,就是当前值是二维数组中它的左下角的值来推导出来的)

点击查看代码
class Solution(object):
    def countSubstrings(self, s):
        """
        :type s: str
        :rtype: int
        """
        # 解法一:动态规划
        # dp[i][j]代表[i,j]对应的s的片段是否为回文子串,值为false/true
        # 若首尾相等s[i]==s[j],则有三种情况s='a'则i==j;若s='aa',则i+1==j;若s='abxxxa',则j-i>1

        # 构造dp二维数组
        dp = [[False]*len(s) for _ in range(len(s))]
        # 初始化,略过

        # 实时更新回文子串个数
        result = 0

        # 开始遍历(从下到上,从左到右)
        # 难点:这里i倒序遍历是因为递推公式的第二种情况,要先知道dp[i+1][j-1]再求dp[i][j],相当于从左下角推导至当前值
        for i in range(len(s)-1, -1, -1):  # 第二个-1代表截至0
            for j in range(i, len(s)):     # !!!!!!! j也就是横坐标从i开始增加,因为dp[i][j]是从i到j !!!!!
                if s[i] == s[j]:
                    if j-i<=1:     # 合并情况一、二(必然是回文子串)
                        result += 1
                        dp[i][j] = True
                    elif dp[i+1][j-1]:    # 情况三(此情况下,如果中间段是回文子串,则向外扩宽1后认为回文子串)
                        result += 1
                        dp[i][j] = True
        return result
                       

        # 解法二:双指针(略)
        

516.最长回文子序列(可以不连续,所有dp数组代表原字符串在[i,j]范围内的片段中回文子序列的最长长度;这样构造是为了更好的得到递推公式)

点击查看代码
class Solution(object):
    def longestPalindromeSubseq(self, s):
        """
        :type s: str
        :rtype: int
        """
        # 动态规划,这道题回文子序列是可以从s中不连续提取元素来构成的
        # dp[i][j]代表[i,j]范围内回文子序列的最长长度
        # 构造二维dp数组
        dp = [[0]*len(s) for _ in range(len(s))]
        # 初始化,因为[i,j]范围内找回文子序列肯定是向中间靠拢的,那最中间是遍历不到的,需要初始化
        for i in range(len(s)):
            dp[i][i] = 1    # 一个字母也是一个回文子序列,长度为1
        # 开始遍历,同理因为由左下角推导本位置,i从下到上,j从i+1开始然后从左到右遍历
        for i in range(len(s)-1, -1, -1):
            for j in range(i+1, len(s)):  # 前面初始化过[i][i]的情况,这里从i+1开始
                # 判断逻辑
                if s[i] == s[j]:
                    dp[i][j] = dp[i+1][j-1] + 2    # 在中间片段的回文子序列基础上加i和j对应值,就是+2
                else:
                    dp[i][j] = max(dp[i+1][j], dp[i][j-1])    # 相当于添加任意一边的元素后,回文子序列不变

        return dp[0][len(s)-1]  # 返回从0到末尾的回文子序列的最长长度

        

PS:动态规划终于学完了,好充实的题量,前面背包那些很多没懂,后面股票、子序列问题能听懂,但是想不到要讨论的那么多情况。还需多刷呀。
今天天气阴,吃了好吃的粤菜早茶,货真价值味道也好,就是给我腻的嘞,还是浅尝比较适合我,赶紧来了个豌杂面缓过来了。

标签:子串,随想录,len,range,647,序列,dp,回文
From: https://www.cnblogs.com/tristan241001/p/18546834

相关文章

  • 代码随想录:有序数组的平方
    代码随想录:有序数组的平方仍然是双指针,一开始也想到了双指针,不过很笨的创造了两个数组,一个负数的一个正数的,两个数组比大小后插入。但其实可以直接把原数组平方后,从左右两边插入。有两点值得注意:1.已知数组大小的情况下,可以直接倒着插入数组。2.创建vector时需要指定元素的个数......
  • 代码随想录算法训练营第一天| 704. 二分查找、35.搜索插入位置、27. 移除元素、977.有
    文档讲解:代码随想录视频讲解:代码随想录状态:完成4道题一、数组理论基础数组:连续内存空间,存储类型相同的元素集合,适合读不适合写注意:Python里可以存储不同类型的元素,但刷题时都是按照相同元素去做的相同元素占用存储的空间大小是一样的,下一个元素的位置就确定了数组时间......
  • 代码随想录算法训练营第二天| 209.长度最小的子数组、59. 螺旋矩阵 II
    文档讲解:代码随想录视频讲解:代码随想录状态:完成2道题滑动窗口滑动窗口:两个指针一前一后组成滑动窗口,并计算滑动窗口中的元素的问题适用场景:字符串匹配问题、子数组问题、定长问题滑动窗口模板:如果一个字符进入窗口,应该增加windows计数器;如果一个字符将移除窗口的......
  • 代码随想录算法训练营第三十天| 452. 用最少数量的箭引爆气球 、435. 无重叠区间 、76
    452.用最少数量的箭引爆气球思路:以前做过最大不相交子序列的题,这次也是往这根据某一端排序的思路想的,排序后如下图,只需要维护一个公共序列的右边界r就可以了,下一次判断时,只需要判断子区间的左边是否小于r。这个题有点坑的是使用Arrays排序,如果使用昨天的方法:Arra......
  • 代码随想录算法训练营 | 200.岛屿的数量
    岛屿的数量题目链接:https://leetcode.cn/problems/number-of-islands/此题目要点:dfs和bfs都可以解决此题,但是使用dfs代码会更加的简洁首先对grid进行遍历,每一个节点都进行检查,判断是否是1(陆地)如果是,则进行dfs深搜,并将所有搜到的岛屿节点全置为0,表示此块岛屿已经被搜过了,防......
  • 代码随想录算法训练营day45| 115.不同的子序列 583. 两个字符串的删除操作 72.
    学习资料:https://programmercarl.com/0115.不同的子序列.html#算法公开课动态规划系列之编辑距离问题学习记录:115.不同的子序列(当遇到相同字母时,可以选择也可以不选;刚开始没看懂;dp[i][j]是对应i-1结尾和j-1结尾,这样的目的是方便第一行和第一列初始化)点击查看代码classSolut......
  • 代码随想录:二分查找
    代码随想录:二分查找二分法标志:数组顺序排列且无重复简单的二分法,写法是左闭右闭的写法,此种情况的left可以等于right,故while里有等号。classSolution{public:intsearch(vector<int>&nums,inttarget){intleft=0;intright=nums.size()-1;......
  • 代码随想录:移除元素
    代码随想录:移除元素题目中的原地指的是不能开创新的数组。简单双指针解决问题,实际上是vector中的erase的实现原理//erase和迭代器的使用方法std::vector<int>vec={1,2,3,4,5};autoit=vec.begin()+2;//指向元素3//这所谓迭代器其实就是封装后的指针啊vec.era......
  • 处理回文串的两种方法:动态规划 | 马拉车(Manacher)算法
    一.前言对于回文串的处理方法有很多,还有中心扩展、哈希等方法。这里只是介绍两种我觉得有用的方法。这里的两种方法不针对的某一种特定题目,他们是一种解题思路,这两个算法像一个工具一样,在有需要的时候使用。二.一维动态规划首先介绍一下这个算法的作用,我们预处理出一个一维d......
  • 代码随想录算法训练营第二十五天| leetcode491.递增子序列、leetcode46.全排列、leetc
    1leetcode491.递增子序列题目链接:491.非递减子序列-力扣(LeetCode)文章链接:代码随想录视频链接:回溯算法精讲,树层去重与树枝去重|LeetCode:491.递增子序列_哔哩哔哩_bilibili思路:用之前的方法,结果翻车了,好好看视频学新技能吧1.1视频后的思路真的没想到用set来去重,还是基......