动态规划Day34:回文

647. 回文子串

DP 数组定义dp[i][j] 表示字符串 s 中,下标从 ij 的子串 s[i...j] 是否为回文子串(true= 是,false= 否)。

状态转移

  • s[i] == s[j]

    • 若子串长度≤2(j-i≤1,如单个字符、两个相同字符),直接判定为回文(dp[i][j]=true);

    • 若子串长度 > 2,则依赖内层子串 s[i+1...j-1] 的结果(dp[i+1][j-1]==true 时,dp[i][j]=true)。

遍历顺序 :从后往前遍历 i(保证计算 dp[i][j] 时,dp[i+1][j-1] 已被计算),ji 往后遍历(只处理 i≤j 的有效子串),每判定一个回文子串就计数 + 1。

cpp 复制代码
    int countSubstrings(string s) {
        vector<vector<bool>> dp(s.size(), vector<bool>(s.size(), false));
        int res = 0;
        for(int i = s.size() - 1; i >= 0; i--){
            for(int j = i; j < s.size(); j++){
                if(s[i] == s[j]){
                    if(j - i <= 1){
                        dp[i][j] = true;
                        res++;
                    } else if(dp[i + 1][j - 1] == true){
                        dp[i][j] = true;
                        res++;
                    }
                }
            }
        }
        return res;
    }

516. 最长回文子序列

求子序列,非连续,所以对不相等的情况还需要处理

DP 数组定义dp[i][j] 表示字符串 s 中,下标 ij 区间内的最长回文子序列长度

状态转移

  • s[i] == s[j]

    • 子区间长度 = 1(j-i=0):只有 1 个字符,dp[i][j]=1

    • 子区间长度 = 2(j-i=1):两个相同字符,dp[i][j]=2

    • 子区间长度 > 2:当前两个字符可拼接在内部最长回文子序列两侧,dp[i][j] = dp[i+1][j-1] + 2

  • s[i] != s[j]:取「去掉 i 的子区间」或「去掉 j 的子区间」的最大值,dp[i][j] = max(dp[i+1][j], dp[i][j-1])

遍历与结果

  • 逆序遍历 i(保证计算 dp[i][j] 时,dp[i+1][j]/dp[i][j-1] 已计算),ji 往后遍历;

  • 每次更新 res 为当前最大的 dp[i][j],最终 res 即为整个字符串的最长回文子序列长度。

cpp 复制代码
int longestPalindromeSubseq(string s) {
        vector<vector<int>> dp(s.size(), vector<int>(s.size(), 0));
        int res = 0;
        for(int i = s.size() - 1; i >= 0; i--){
            for(int j = i; j < s.size(); j++){
                if(s[i] == s[j]){
                    if(j - i == 0){
                        dp[i][j] = 1;
                    }
                    else if(j - i == 1){
                        dp[i][j] = 2;
                    }
                    else if(dp[i + 1][j - 1] > 0){
                        dp[i][j] = dp[i + 1][j - 1] + 2;
                    }
                } else {
                    dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);
                }
                res = max(res, dp[i][j]);
            }
        }
        return res;
    }
相关推荐
invincible_Tang几秒前
AcWing 796. 子矩阵的和 _
数据结构·算法
米粒15 分钟前
力扣算法刷题 Day 8
算法·leetcode·职场和发展
Sakinol#12 分钟前
Leetcode Hot 100 —— 普通数组
算法·leetcode
@Mike@20 分钟前
【算法】高精度
算法
leo__52021 分钟前
MHT多假设跟踪算法(Multiple Hypothesis Tracking)MATLAB实现
开发语言·算法·matlab
ShineWinsu21 分钟前
对于C++中unordered_set的详细介绍
数据结构·c++·算法·面试·stl·哈希表·unordered_set
吃着火锅x唱着歌21 分钟前
LeetCode 456.132模式
数据结构·算法·leetcode
二木九森24 分钟前
LeetCode-寻找环形链表的入口
算法·leetcode·链表
飞Link31 分钟前
耳机连接电脑时调节耳机音量电脑音量也会随着改变
算法·电脑
此方ls38 分钟前
机器学习聚类算法一——K均值
算法·机器学习·聚类