首页 > 其他分享 >动态规划:最长回文子串

动态规划:最长回文子串

时间:2024-08-14 09:55:01浏览次数:11  
标签:子串 length range 长度 最长 dp 回文

目录

题目

思路

解题过程

复杂度

code 


题目

        给你一个字符串 s,找到 s 中最长的 回文子串

示例 1:

输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。

示例 2:

输入:s = "cbbd"
输出:"bb"

提示:

  • 1 <= s.length <= 1000
  • s 仅由数字和英文字母组成

思路

        使用动态规划方法来解决最长回文子串问题。动态规划通过构建一个表格来存储中间结果,避免重复计算,从而提高效率。


解题过程

  • 初始化

  1. 创建一个 n×n 的布尔表 dpdp[i][j] 表示子串 s[i:j+1] 是否为回文。
  2. 初始化这个二维表。对于长度为1的子串(即单个字符),它们自然是回文串,因此dp[i][i](所有对角线上的元素)都应该被设置为True
    n = len(s)  

	dp = [[False] * n for _ in range(n)]  

	for i in range(n):  

	    dp[i][i] = True
  • 填表

  1. 回文子串的长度可以从2开始逐渐增加,可以从长度为2的子串开始检查,然后是长度为3的子串,依此类推,直到长度为n的子串。对于每个长度,我们遍历所有可能的起始索引。
  2. 对于任意dp[i][j](其中i < j),如果s[i] == s[j](即子串的两个端点字符相同),我们需要检查子串内部(即s[i+1:j])是否也是回文串。这可以通过查看dp[i+1][j-1]的值来实现。如果dp[i+1][j-1]True,则dp[i][j]也为True。此外,对于长度为2或3的子串,我们可以直接通过比较字符来判断,而无需检查内部子串,因为这样的子串要么只包含两个相同的字符(长度为2),要么包含三个字符且首尾相同、中间字符任意(长度为3,但首尾相同的情况已经通过比较字符确定了)。
for length in range(2, n+1):  # 子串长度从2到n  

	    for i in range(n - length + 1):  # 遍历所有可能的起始索引  

	        j = i + length - 1  # 计算结束索引  

	        if s[i] == s[j] and (length == 2 or dp[i+1][j-1]):  

	            dp[i][j] = True
  • 更新最长回文子串的起始位置和长度:

         在填表的过程中,我们还需要跟踪记录到目前为止找到的最长回文子串的起始位置和长度。这可以通过比较当前回文子串的长度和已记录的最长长度来实现,并在需要时更新这些信息

max_length = 1  
start = 0  
for length in range(2, n+1):  
    for i in range(n - length + 1):  
        j = i + length - 1  
        if dp[i][j] and length > max_length:  
            max_length = length  
            start = i
  • 结果提取

      根据记录的最长回文子串的起始位置和长度,从原字符串中提取出这个子串作为结果。

longest_palindrome = s[start:start+max_length]

复杂度

  • 时间复杂度: O(n^2),要检查字符串中所有可能的子串(即从每个索引开始,长度为2到n的所有子串),这导致了一个双重循环,每层循环都遍历了字符串的一部分。
  • 空间复杂度: O(n^2),因为需要一个 n×n 的布尔表来存储每个子串是否为回文的状态。

code 

class Solution(object):
    def longestPalindrome(self, s):
        if len(s) < 2:
            return s

        n = len(s)
        max_len = 1
        start = 0
        dp = [[False] * n for _ in range(n)]

        for i in range(n):
            dp[i][i] = True

        for j in range(1, n):
            for i in range(0, j):
                if s[i] == s[j]:
                    if j - i < 3:
                        dp[i][j] = True
                    else:
                        dp[i][j] = dp[i + 1][j - 1]

                if dp[i][j] and j - i + 1 > max_len:
                    max_len = j - i + 1
                    start = i

        return s[start:start + max_len]

标签:子串,length,range,长度,最长,dp,回文
From: https://blog.csdn.net/Sxiaocai/article/details/141182236

相关文章

  • 最长
    https://www.luogu.com.cn/problem/P4310第2题   最长 查看测评数据信息给定一个长度是n的序列a[1,2,...n],现在你需要构造一个长度为m的数组b[1,2,...m],需要满足如下条件:(1)b是a的子序列(2)b[i]&b[i-1]!=0(2<=i<=m)问构造出b后,m的最大值是多少。输入格式 输入文件......
  • 最长的一帧学习(待补)
    文章目录一、osgViewer::ViewerBase::frame()1.osgViewer::View::init()2.osgViewer::Viewer::realize(),窗口和场景的“设置”工作part1GraphicsContextpart1.1通过阅读osgViewer::View::setUpViewInWindow()了解osg最基础的操作part2DisplaySettingspart3遍历......
  • 9_回文数
    9_回文数【问题描述】给你一个整数x,如果x是一个回文整数,返回true;否则,返回false。(回文数指的是从左到右看和从右向左看完全一样的数字。)示例:输入:x=121输出:true解:【算法设计思想】主要是利用取模运算,对于一个数x进行x%10的运算即可得到它的最后一位数字,依此把逆......
  • Leetcode热题100-128.最长连续序列
    Leetcode热题100-128.最长连续序列1.题目描述2.解题思路3.代码实现1.题目描述128.最长连续序列2.解题思路使用哈希集合的思想:初始化一个unordered_set并将nums中所有元素放入集合中;遍历数组,依次判断当前元素是否为连续序列的开始,若是则求出当前连续序列......
  • 验证回文串
    如果在将所有大写字符转换为小写字符、并移除所有非字母数字(一开始根本没看到数字两个字)字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。字母和数字都属于字母数字字符。给你一个字符串 s,如果它是 回文串 ,返回 true ;否则,返回 false 。示例1......
  • 代码随想录day23 || 39 组合总和,40 组合总和2,131 分割回文串
    39组合总和funccombinationSum(candidates[]int,targetint)[][]int{ //思路,组合问题考虑回溯算法,考虑到元素可能重复问题,所以,树的最大深度应该是target/min(candudates)+1 varpath=[]int{} varres=[][]int{} backtracking(target,candidates,&path,&res......
  • leetcode 718. 最长重复子数组,leetcode 1143. 最长公共子序列
    leetcode718和leetcode1143两道十分相似的题,就不放题目了思路实际上区别就在于一个要求连续数组,另一个要求不连续的序列。二者的dp表达式和状态转移其实是不一致的,前者f[i][j]代表nums1以i结尾nums2以j结尾的最长子数组长度,后者代表nums1以i结尾nums2以j结尾的区间内存......
  • 最长上升子序列
    普通#include<iostream>usingnamespacestd;#include<algorithm>#include<cstring>constintN=5010;intn,f[N];inta[N];intmain(){ cin>>n; for(inti=1;i<=n;i++)cin>>a[i]; for(inti=1;i<=n;i++......
  • 算法力扣刷题记录 六十八【131.分割回文串】
    前言回溯章节第六篇。切割问题。记录六十八【131.分割回文串】。一、题目阅读给你一个字符串s,请你将s分割成一些子串,使每个子串都是回文串。回文串指字符串从前读和从后读一样。返回s所有可能的分割方案。示例1:输入:s="aab"输出:[["a","a","b"],["aa","b"]]......
  • 代码随想录 day 47 回文子串 | 最长回文子序列
    回文子串回文子串解题思路dp数组的状态是判断以i结尾,j开始的字符串是否为回文,用bool类型存储,之后当i和j的字符串相等时,通过计算它们之间的距离和判断它们之间是否为回文串来进行递归。知识点回文,动态规划心得如果不看题解根本想不到怎么做最长回文子序列最长回文子序列......