【leetcode】【动态规划】最长回文子序列

【leetcode】最长回文子序列

leetcode题目地址

题目

给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。

子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。

示例 1:
输入:s = “bbbab”
输出:4
解释:一个可能的最长回文子序列为 “bbbb” 。

示例 2:
输入:s = “cbbd”
输出:2
解释:一个可能的最长回文子序列为 “bb” 。

代码

动态规划算法。初始化n ⋅ n n\cdot nnn大小的d p dpdp数组,d p [ i ] [ j ] dp[i][j]dp[i][j]表示字符串i iij jj内的最长回文字序列的长度。转移方程为:

d p [ i ] [ j ] = { d p [ i + 1 ] [ j − 1 ] + 2 , s t r [ i ] = = s t r [ j ] m a x ( d p [ i + 1 ] [ j ] , d p [ i ] [ j − 1 ] ) , o t h e r w i s e dp[i][j]= \left\{\begin{matrix} & dp[i+1][j-1]+2 & ,str[i]==str[j]\\ & max(dp[i+1][j], dp[i][j-1]) & ,otherwise \end{matrix}\right.dp[i][j]={dp[i+1][j1]+2max(dp[i+1][j],dp[i][j1]),str[i]==str[j],otherwise

再注意当i = = j i==ji==ji + 1 = = j i+1==ji+1==j的情形即可。

自己写的屑代码:

class Solution {
public:
    int longestPalindromeSubseq(string s) {
        int n = s.size();
        vector<vector<int>> arr(n, vector<int>(n));
        for(int i=0;i<n;i++) arr[i][i] = 1;
        for(int i=0;i<n-1;i++) arr[i][i+1] = s[i] == s[i+1] ? 2 : 1;
        for(int k=1;k<n;k++){
            for(int i=0;i<n-k;i++){
                arr[i][i+k] = max(arr[i][i+k-1], arr[i+1][i+k]);
                if(s[i] == s[i+k]) arr[i][i+k] = max(arr[i][i+k], arr[i+1][i+k-1] + 2);
            }
        }
        return arr[0][n-1];
    }
};

为什么想写一下呢,主要是最近正活儿干的太慢。。。啊不,是在上面的代码中想着循环的层次顺序的问题,遍历的要点我认为是保证其依赖的子区间全部都计算过了,最简单的思路就是如以上代码,先遍历区间的长度k ( k = j − i ) k(k=j-i)k(k=ji),再遍历区间的起始点i ii,这样最易于理解,而遍历i iij jj在脑子不清楚(比如写代码的时候)就会自我怀疑,它这个子区间都处理了吗?(类似于“我今天出门锁门了吗?”)。下面用excel简单画了个图看一下——我也是闲的。。。

在这里插入图片描述
要点说过了,在于保证当前区间的真子区间(就是不包括自己,我随便编的概念)都已经处理过了,我的代码为左图,下面的官方代码为中间图。

官方代码:

class Solution {
public:
    int longestPalindromeSubseq(string s) {
        int n = s.length();
        vector<vector<int>> dp(n, vector<int>(n));
        for (int i = n - 1; i >= 0; i--) {
            dp[i][i] = 1;
            char c1 = s[i];
            for (int j = i + 1; j < n; j++) {
                char c2 = s[j];
                if (c1 == c2) {
                    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][n - 1];
    }
};

版权声明:本文为qq_40690815原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。