前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Leetcode 5. 最长回文子串

Leetcode 5. 最长回文子串

作者头像
zhipingChen
发布2019-05-17 12:04:33
8170
发布2019-05-17 12:04:33
举报
文章被收录于专栏:编程理解编程理解

题目描述

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

示例 1:

输入: "babad"

输出: "bab"

注意: "aba" 也是一个有效答案。

示例 2:

输入: "cbbd"

输出: "bb"

解法1

动态规划,以

f(i,j)
f(i,j)

表示字符串中下标

i
i

j
j

的字符串是否为回文串,包括首尾下标字符,若

s[i]==s[j]
s[i]==s[j]

。则有:

f(i,j) = \begin{cases} True, & \text{ $j-i \lt 3$ }\\ f(i+1,j-1), & \text{ $j-i \ge 3$ } \end{cases}
f(i,j) = \begin{cases} True, & \text{ $j-i \lt 3$ }\\ f(i+1,j-1), & \text{ $j-i \ge 3$ } \end{cases}

借助二维数组记录

flag[i][j]
flag[i][j]

记录

f(i,j)
f(i,j)

状态。

代码语言:javascript
复制
class Solution:
    def longestPalindrome(self, s: str) -> str:
        ret,flag='',[[False]*len(s) for i in range(len(s))]
        for j in range(len(s)):
            for i in range(j,-1,-1):
                if s[i]==s[j]:
                    if j-i<3 or flag[i+1][j-1]:
                        flag[i][j]=True
                        ret=s[i:j+1] if j-i+1>len(ret) else ret
        return ret

解法2

解法1借助了二维数组空间来完成计算,这里优化数组空间为一维数组。

由解法1可知,对于下标

j-1
j-1

的一维数组空间

flag[i][j-1]
flag[i][j-1]

:

flag[0][j-1],flag[1][j-1],flag[2][j-1]...flag[j-1][j-1]
flag[0][j-1],flag[1][j-1],flag[2][j-1]...flag[j-1][j-1]

表示

s[i][j-1] (0 \le i \le n-1)
s[i][j-1] (0 \le i \le n-1)

是否为回文串。

对于下标

j
j

的一维数组空间

flag[i][j]
flag[i][j]

,如果

s[i]==s[j]
s[i]==s[j]

,则

flag[i][j]
flag[i][j]

取决于

flag[i+1][j-1]
flag[i+1][j-1]

。这里可以使用一维数组

flag
flag

记录状态,则

flag[i]
flag[i]

取决于

flag[i+1]
flag[i+1]

代码语言:javascript
复制
class Solution:
    def longestPalindrome(self, s: str) -> str:
        ret,flag='',[False]*len(s)
        for j in range(len(s)):
            for i in range(j+1):
                if s[i]==s[j] and (j-i<3 or flag[i+1]):
                    flag[i]=True
                    ret=s[i:j+1] if j-i+1>len(ret) else ret
                else:
                    flag[i]=False
        return ret

解法3

前面两种解法都需要

O(n^2)
O(n^2)

的计算复杂度,解法3采用 manacher 算法,首先使用字符串中不存在的字符,扩充原始字符串,以此忽略奇数和偶数长度的影响。然后由左向右遍历字符串中元素,以每个元素为对称轴,扩散求回文串长度。

若是填充后进行常规的扩散求回文串,则复杂度依然是

O(n^2)
O(n^2)

manacher 算法中记录已访问回文串最右元素下标 maxrt,及当前的对称轴下标 cen。则继续访问时,若元素下标 imaxrt 之前,根据对称性,以 i 位置为对称轴的回文串已全部访问,或已访问 s[i:maxrt+1] 部分,剩下的部分可继续访问。通过该方式避免了对每个下标位置的重复扩散访问,满足

O(n)
O(n)

的计算复杂度。

代码语言:javascript
复制
class Solution:
    def longestPalindrome(self, s: str) -> str:
        s='#'+'#'.join(list(s))+'#'
        ret,m,cen,maxrt='',[0]*len(s),0,0
        for i in range(len(s)):
            if i<maxrt:
                m[i]=min(m[2*cen-i],maxrt-i)
            while i-m[i]-1>=0 and i+m[i]+1<len(s) and s[i-m[i]-1]==s[i+m[i]+1]:
                m[i]+=1
            if i+m[i]>maxrt:
                cen,maxrt=i,i+m[i]
            if m[i]>len(ret):
                ret=s[i-m[i]:i+m[i]+1].replace('#','')
        return ret
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.05.15 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档