题目
给定一个字符串s,找到s中最长的回文子串。s仅由数字和英文字母组成。
示例:
输入:s = "babad" 输出:"bab" 解释:"aba" 同样是符合题意的答案
输入:s = "cbbd" 输出:"bb"
1、思路
看到这道题,暴力想法就是直接遍历出所有的子串,对每个子串进行回文判断,并记录下最长的子串,but,时间和内存都消耗极大,遂pass。
在仔细一看好像属于动态规划的最优子结构问题,什么是动态规划?什么是最优子结构?动态规划的最优子结构问题如何解决?
动态规划
如果能够将一整个决策过程分成若干个互相联系的阶段性决策过程,从而使得最终的整个过程达到最好的效果。各个阶段决策的选取不能任意确定,它依赖于当前面临的状态,又影响着下一个状态,这样就是把一个问题看作是一个前后关联具有链状结构的过程,称为多阶段决策问题。
在多阶段决策问题中,各个阶段采取的决策,一般来说是与时间有关的,决策依赖于当前状态,又随即引起状态的转移,一个决策序列就是在变化的状态中产生出来的,故有“动态”的含义,称这种解决多阶段决策最优化的过程为动态规划方法。
简单来说,就是将一个复杂问题,分解成很多子问题,并将子问题的求解结果存储起来避免重复求解,按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。
最优子结构(最优化原理)
不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略。即一个最优化策略的子策略总是最优的。那么要解决这个问题,我们首先要写出适合该问题的状态转移方程以及动态规划的边界条件。
分析
寻找字符串s的最长回文子串,对于一个长度大于2的回文串,如果去除首尾字符,它仍然是一个回文串,例如"ababa",去掉首尾,"bab"仍然为回文串,这就是动态规划的状态之间的影响关系。我们使用P(i, j)表示子串s[ i : j ]是否为回文串,那么它的动态规划的状态转移方程为:
即只有s[i+1, j-1]是回文串,并且s的第i个和j个字母相同时,s[ i : j ]才为回文串。
当s的长度为1时,一定为回文串。
当s的长度为2时,如果两个字母相同,一定为回文串。则动态规划的边界条件为:
则最长的回文串即为P(i, j)中华j - i + 1的最大值。
python
class Solution:
def longestPalindrome(self, s: str) -> str:
n = len(s)
if n == 1:
return s
if n == 2:
if s[0] == s[1]:
return s
else:
return s[0]
p = [[False]*n for _ in range(n)]
max_len = 1
start = 0
if n > 2:
for L in range(2, n+1): # 枚举子串长度
for i in range(n): # i为左边界
j = L + i -1 # j为右边界
if j >= n:
break
if s[i] != s[j]:
p[i][j] = False
else:
if j- i < 3: # 边界条件
p[i][j] = True
else:
p[i][j] = p[i+1][j-1] # 状态转移方程
if p[i][j] and j - i + 1 > max_len:
max_len = j - i + 1
start = i
return s[start: start + max_len]