5.最长回文子串

在这里插入图片描述

1.中心扩展算法

事实上,只需使用恒定的空间,我们就可以在 O(n2) 的时间内解决这个问题。

我们观察到回文中心的两侧互为镜像。因此,回文可以从它的中心展开,并且只有 2n - 1 个这样的中心。
你可能会问,为什么会是 2n - 1 个,而不是 n 个中心?原因在于所含字母数为偶数的回文的中心可以处于两字母之间(例如 “abba” 的中心在两个 ‘b’ 之间)。

class Solution:
    def longestPalindrome(self, s: str) -> str:
	    """
	    定义一个检查函数,
	    如果可以向两边扩展那么左右索引各自加一
	    否则输出此中心的最大回文长度
	    """
        def expandaroundcenter(s:str,l:int,r:int)->int:
            while(l>=0 and r<len(s) and s[l]==s[r]):
                l-=1
                r+=1
        	"此处是减1,而不是加1,因为l,r是在判断后加的1"
            return r-l-1
        
        end=start=0
        for i in range(len(s)):
        	"判断以i为中心的奇数长度"
            len1=expandaroundcenter(s,i,i)
            "判断以i,i+1为中心的偶数长度"
            len2=expandaroundcenter(s,i,i+1)
            maxlen= len1 if len1>len2 else len2
            if(maxlen>end-start):
            	"""
            	此处需要减一,因为我们使用了取整,比如baab,maxlen=4 
            	start==1-(4-1)//2==0
            	"""
                start=i-(maxlen-1)//2
                end=i+maxlen//2
        return s[start:end+1]

2.动态规划算法

动态规划与递归类似都把问题分解为子问题,DP适合子问题重叠,最优化方法.
分析问题过程如下
1.分析问题空间
2.建立递归式(状态转移方程)
3.自底向上计算
4.记录最优方案的详细过程(可选)

在这个问题中,我们可以用到上一次的子问题
1.
设P(i,j)为s[i,j]是否为回文子串,是的话为True,否则为False
2.
可以得出 P(i,j)=True if s[i]==s[j] and P(i+1,j-1)
这就是状态转移方程,OK 问题得解.
3.
从l=0 ->len(s) 分别计算子问题
4.
把结果记录在s[i,j+1]

class Solution:
    def longestPalindrome(self, s: str) -> str:
        t=len(s)
        if(t==0 or t==1):
            return s
        #建立二维数组
        p=[[False for i in range(t)] for i in range(t)]
        maxlen=0
        #子问题从0 开始       
        for l in range(t):
        #注意i的索引范围
            for i in range(t-l):
                j=i+l
                if(s[i]==s[j] and (l<2 or p[i+1][j-1])):
                    p[i][j]=True
                    if(l+1>maxlen):
                        maxlen=l+1
                        ans=s[i:j+1]
        return ans

另一种动态递归方法
利用的是上一次计算的最大长度

   def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
       
        if len(s) < 2 or s == s[::-1]:
            return s
        n = len(s)
        start, maxlen = 0, 1
 
        for i in range(1, n):
 
            odd = s[i - maxlen - 1:i + 1]  
            # 
            even = s[i - maxlen:i + 1]  
            #e.g cbabd i=3时 maxlen=1 
            if i - maxlen - 1 >= 0 and odd == odd[::-1]:
                start = i - maxlen - 1
                maxlen += 2
                continue
            # e.g. bbbbbb i=3 时 maxlen=3
            if i - maxlen >= 0 and even == even[::-1]:
                start = i - maxlen
                maxlen += 1
                
        return s[start:start + maxlen]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值