516. 最长回文子序列

题目链接:

本题考察区间 \(dp\)
\(f[i][j]\) 表示子串 \(i \sim j\) 中的最长回文子序列的长度。
思考状态转移方程。因为是判断回文的问题,考虑首尾元素是否相同。
若首尾元素相同,则考虑去掉首尾元素之后子串的最长回文子序列的长度 + 2(首、尾元素各一个)
反之若首尾元素不相同,则分别去掉首和尾,看子串的最长回文子序列长度的最大值。

实现一、递推

class Solution {
public:
    static const int N = 1010;
    int f[N][N];
    int longestPalindromeSubseq(string s) {
        int n = s.size();
        for (int i = n - 1; i >= 0; i--) {
            f[i][i] = 1;//长度为1的子串
            for (int j = i + 1; j < n; j++) {//长度不为1的子串
                if (s[i] == s[j]) f[i][j] = f[i + 1][j - 1] + 2;
                else f[i][j] = max(f[i + 1][j], f[i][j - 1]);
            }
        }
        return f[0][n - 1];
    }
};

实现二、记忆化搜索

class Solution {
public:
    int longestPalindromeSubseq(string s) {
        int n = s.size();
        int memo[n][n];
        memset(memo, -1, sizeof memo);//初始化为-1,表示没有计算过
        function<int(int, int)> dfs = [&] (int i, int j) -> int {
            if (i > j) return 0;//空串
            if (i == j) return 1;//只有一个字母
            int &res = memo[i][j];//引用,简化代码
            if (res != -1) return res;
            if (s[i] == s[j]) return res = dfs(i + 1, j - 1) + 2;
            return res = max(dfs(i, j - 1), dfs(i + 1, j));
        };
        return dfs(0, n - 1);
    }
};
posted @ 2024-04-09 22:19  胖柚の工作室  阅读(14)  评论(0)    收藏  举报