516. 最长回文子序列

516. 最长回文子序列

题目链接:516. 最长回文子序列(中等)

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

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

示例 1:

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

示例 2:

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

提示:

  • 1 <= s.length <= 1000

  • s 仅由小写英文字母组成

解题思路

注意本题与647. 回文子串 的不同:回文子串是要连续的,回文子序列可不是连续的!

求回文子串和回文子序列都是动态规划的经典题目。

  1. dp数组的含义

    dp[i][j]表示字符串s[i,j]范围内最长的回文子序列的长度。

  2. 递推公式

    关键看s[i]s[j]是否相同

    • s[i] == s[j],那dp[i][j]就等于字符串s[i+1,j-1]范围内最长的回文子序列的长度加上字符s[i]s[j]。即:dp[i][j]=dp[i+1][j-1]+2

    • s[i] != s[j],那就考虑在s[i+1,j-1]的基础上加入左边的字符s[i]或右边的字符s[j]所能得到的最长长度。

      • 加入左边的字符s[i]dp[i][j]=dp[i][j-1]

      • 加入右边的字符s[j]dp[i][j]=dp[i+1][j]

      取两者的最大值:dp[i][j]=max(dp[i][j-1],dp[i+1][j])

  3. dp的初始化

    首先考虑i = j ,从递推公式:dp[i][j]=dp[i+1][j-1]+2可以看出:递推公式是计算不到 ij相同时的情况。所以需要手动初始化一下:当i=j,那么dp[i][j]一定是等于1的,即:一个字符的回文子序列长度就是1。

    其他情况dp[i][j]初始为0就行,这样递推公式:dp[i][j] = max(dp[i + 1][j], dp[i][j - 1])dp[i][j]才不会被初始值覆盖。

  4. 遍历顺序

    从递推公式来看,遍历i的时一定要从下到上遍历,遍历j时一定要从左到右遍历。

C++

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

JavaScript

/**
 * @param {string} s
 * @return {number}
 */
var longestPalindromeSubseq = function(s) {
    const dp = new Array(s.length).fill().map(item => Array(s.length).fill(0));
    for (let i = 0; i < s.length; i++) {
        dp[i][i] = 1;
    }
    for (let i = s.length - 1; i >= 0; i--) {
        for (let j = i + 1; j < s.length; j++) {
            if (s[i] == s[j]) {
                dp[i][j] = dp[i + 1][j - 1] + 2;
            } else {
                dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]);
            }
        }
    }
    return dp[0][s.length - 1];
};

 

 

 

posted @ 2022-03-23 10:33  wltree  阅读(66)  评论(0编辑  收藏  举报