1、问题描述
给定一个字符串s,找到其中最长的回文子序列,并输出其最大长度。可以假设s的最大长度为1000。
例如:输入的字符串s=“bbbab”,这时最长的回文子序列为"bbbb",长度为4,所以输出为4
2、解题思路
- 边界条件:输入字符串s为空,直接返回0。
- 思路1:这道题和leetcode - [字符串、动态规划] - (1)最大回文子串类似。只不过这里子序列中出现的字符在原字符串中可以是不连续的,而子串则要求必须连续。所以这道题仍然采用动态规划方法,具体步骤如下:
- (一)定义状态
- f [ i ] [ j ] f[i][j] f[i][j]表示子串 s [ i , j ] s[i,j] s[i,j]中最长回文子序列的长度;
- (二)定义状态转移方程
- 1、如果 s s s的第 i i i个字符和第 j j j个字符相同的话,
- f [ i ] [ j ] = f [ i + 1 ] [ j − 1 ] + 2 f[i][j]=f[i+1][j-1] + 2 f[i][j]=f[i+1][j−1]+2
- 2、如果 s s s的第 i i i个字符和第 j j j个字符不同的话,
- f [ i ] [ j ] = m a x { f [ i + 1 ] [ j ] , f [ i ] [ j − 1 ] } f[i][j]=max\{f[i+1][j],f[i][j-1]\} f[i][j]=max{f[i+1][j],f[i][j−1]}
- 3、注意,在计算二维数组 f f f的值时,应该从上三角的最下面开始, i i i从 n − 1 n-1 n−1变到 0 0 0, j j j从 i + 1 i+1 i+1到 n − 1 n-1 n−1,以确保每个子问题都已经算好了。
- (三)初始化
- f [ i ] [ i ] = 1 f[i][i]=1 f[i][i]=1,单个字符的最长回文子序列长度为1。
- (四)结果
- f [ 0 ] [ n − 1 ] f[0][n-1] f[0][n−1]
3、代码实现
class Solution:
def longestPalindromeSubseq(self, s: str) -> int:
maxlen = 0
if len(s) != 0:
pl = [[0] * len(s) for i in range(0,len(s))]
for l in range(0,len(s)):
l = len(s) - 1 - l
pl[l][l] = 1
for r in range(l + 1,len(s)):
if s[l] == s[r]:
pl[l][r] = pl[l+1][r-1] + 2
else:
pl[l][r] = max(pl[l+1][r],pl[l][r-1])
maxlen = pl[0][len(s) - 1]
return maxlen