leetcode - [字符串、动态规划] - (1)最大回文子串

本文介绍了一种高效算法来找出给定字符串中的最长回文子串。通过两种方法对比,详细阐述了如何利用动态规划在O(n²)时间内解决此问题,并提供了完整的Python代码实现。

1、问题描述

给定一个字符串s,求s得最长回文子串,你可以假设s得最大长度为1000。
例如:输入的字符串为"babad",则输出最大的回文子串为"bab"和"aba"。

2、解题思路

  • 边界条件:输入字符为空,直接返回空串;
  • 思路1:最简单的方法,这道题可以分解为两个步骤:(1)求s的每一个子串p;(2)判断子串p是否为回文串。表示一个子串时,可以用它的起始、终止位置索引对(start,end)来表示。start表示该子串的起始位置,end表示该子串的终止位置。由于这样的索引对有(n+1)n2=n+(n−1)+...+1\frac{(n+1)n}{2}=n+(n-1)+...+12(n+1)n=n+(n1)+...+1对,所以步骤1花费的时间为O(n2)O(n^2)O(n2),而判断每一个子串是否为回文串时,我们可以采用双指针来实现,花费的时间为O(n)O(n)O(n),所以这种方法最终的时间复杂度为O(n3)O(n^{3})O(n3)
  • 思路2:实际上,如果采用动态规划的方法,可以实现在O(n2)O(n^{2})O(n2)的时间内完成回文串的判断,这种具体做法如下:
    (1)定义状态
    我们可以使用一个二维数组ispal来表示一个子串是否为回文串,数组的行坐标表示子串的起始位置,列坐标表示子串的终止位置,数组中元素的值表示以行坐标为起始位置,列坐标为终止位置的子串是否为回文串,例如ispal(0,1)=true表示起始位置为0,终止位置为1的子串为回文串,由于矩阵的终止位置一定大于或等于起始位置,所以矩阵的下三角元素值没有意义。
    (2)定义状态转移方程
    我们清楚这样一些事实:
    a、当子串只有1个字符时,它一定是回文字符串;
    b、当子串的长度超过2个字符时,如果s[l,r]是一个回文串,比如s[l,r]=“abccba”,则将这个回文串的两边(如果可以的话)各往里收缩一个字符之后形成的子串s[l+1,r-1]也一定是一个回文串。即如果s[l,r] == true,则s[l+1,r-1] ==true。
    由上面的的事实可知,当s[l]==s[r],字符串s[l,r]是否为回文串完全由s[l+1,r-1]决定,但这里还需要考虑原字符串去除左右边界之后子串的边界情况:
    这里,我们要求s[l+1,r - 1]至少包含两个字符,才有必要继续判断下去,否则直接根据左右边界是否相等就能判断原字符串是否是回文串,而s[l+1,r-1]至少包含两个字符等价于l+1<r-1,即r-1>2,
    综合上述分析,最终的状态转移方程如下:
    ispal(l,r)={trueifs[l]==s[r] and ispal(l+1,r−1)==true)falseothersispal(l,r)=\begin{cases}true & if s[l]==s[r] \ and \ ispal(l+1,r-1)==true)\\ false & others\end{cases}ispal(lr)={truefalseifs[l]==s[r] and ispal(l+1r1)==true)others
  • 以"s=babad"为例,使用动态规划方法的过程如下:
  • 在这里插入图片描述

3、代码实现

class Solution:
    def longestPalindrome(self, s: str) -> str:
        
        longestp = ""
        
        if len(s) != 0:
            
            ispal =[[False] * len(s) for i in range(len(s))]
            
            for r in range(0,len(s)):
                for l in range(0,r + 1):
                    l = r - l
                    if r - l <= 2:
                        if s[l] == s[r]:
                            ispal[l][r] = True
                    else:
                        if s[l] == s[r] and ispal[l+1][r-1] == True:
                            ispal[l][r] = True
            
            max_len = 0                       
            for l in range(0,len(s)):
                for r in range(l,len(s)):
                    if r - l + 1 > max_len and ispal[l][r] == True:
                        max_len = r - l + 1
                        longestp = s[l: r + 1]
                        
            
        return longestp
       
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Albert_YuHan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值