第一章:动态规划之子序列问题解题模板

labuladong 动态规划之子序列问题解题模板

516. 最长回文子序列

如果暂时想不到状态转移方程,可以先确定base case最终状态,然后通过它们的相对位置,来猜测状态转移方程,猜测dp[i][j]可能从哪些状态转移而来。以本题为例:

  • base case:dp表的左下角三角形为0,对角线元素为1(回文子序列为自己)
  • 最终状态是dp[o][n-1]
  • 对于dp[i][j],它知道了左边元素,下边元素,左下边元素; 此外,通过结合最终状态的位置,所以考虑从左到右从下到上的次序遍历dp表。于是思考状态转移方程及遍历过程:
        for i in range(n-2,-1,-1):
            for j in range(i+1,n):
                if s[i]==s[j]:
                    dp[i][j]=dp[i+1][j-1]+2
                else:
                    dp[i][j]=max(dp[i+1][j],dp[i][j-1])
  1. dp数组的含义:s[i…j] 中最长回文子序列的长度保存在dp[i][j] 中
  2. 状态转移方程:如果i处和j处的字符相同,则从短串s[i+1…j-1]中扩充2(dp[i][j]=dp[i+1][j-1]+2)。 否则继承 s[i+1…j] , s[i…j-1] 的最长回文子序列长度的最大值 (max(dp[i+1][j],dp[i][j-1])
  3. base case: dp 数组先初始化为 0 (而且对角线下半部分的三角形表示i > j, 不可能出现这种情况,因此为0)。i 和 j 指向同一个字符时,回文子序列为其本身, 因此对角线处的dp数组元素初始化为1
class Solution(object):
    def longestPalindromeSubseq(self, s):
        n=len(s)
        dp=[[0 for _ in range(n)] for _ in range(n)]
        for i in range(n):
            dp[i][i]=1

        for i in range(n-2,-1,-1):
            for j in range(i+1,n):
                if s[i]==s[j]:
                    dp[i][j]=dp[i+1][j-1]+2
                else:
                    dp[i][j]=max(dp[i+1][j],dp[i][j-1])
        return dp[0][-1]

   转载规则


《第一章:动态规划之子序列问题解题模板》 M 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
第一章:贪心算法之区间调度问题 第一章:贪心算法之区间调度问题
labuladong贪心算法之区间调度问题 435. 无重叠区间 一天有好多活动,你可以选择不重叠的时间尽量多参加活动。 按照活动结束的时间排序后(不管开始得多早,都不如选择早点结束的活动,这样还能继续选其他活动) 假设当前参加的是活动A
2020-07-31
下一篇 
第一章:经典动态规划:最长公共子序列 第一章:经典动态规划:最长公共子序列
labuladong经典动态规划:最长公共子序列 1143. 最长公共子序列(在dp数组中添加0行和0列可以包含text为空的情况,并且更便于状态转移) dp数组的含义: 对于 text1[0..i-1] 和 text2[0..j-1],
2020-07-31
  目录