动态规划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;
    }
相关推荐
大白话_NOI4 分钟前
【洛谷 P1024 】[NOIP2001 提高组] 一元三次方程求解 - 详细分析与C++实现
c++·算法
Matthew_zhu_5 分钟前
P3374 【模板】树状数组 1 题解
算法
随意起个昵称5 分钟前
区间dp-进阶题目1(进阶合并)
c++·算法·动态规划
伶俜666 分钟前
鸿蒙原生应用实战(四)ArkUI 语音变声器:录音 + 4 种音效 + 音调变换算法
算法·华为·harmonyos
AKA__Zas10 分钟前
芝士算法(滑动窗口片 2.0)
java·算法·leetcode·学习方法
变量未定义~11 分钟前
摆放小球 、dp求解组合数、求解组合数2
数据结构·算法
加油码20 分钟前
位图 BitMap:用一个 bit 管一个状态,空间直接省到位
c++·算法
四代水门22 分钟前
LeetCode刷算法题(C++)
c++·算法·leetcode
一头老黄牛@24 分钟前
飞书 × OpenClaw 接入指南:不用服务器,用长连接把机器人跑起来
数据结构·人工智能·程序人生·算法·决策树·自动化·推荐算法
Passionate.Z31 分钟前
基于FPGA的CLAHE自适应限制对比度直方图均衡算法硬件verilog实现
图像处理·嵌入式硬件·算法·fpga开发·fpga