动态规划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;
    }
相关推荐
Niuguangshuo6 小时前
论文解读:CTC,端到端序列识别的开山之作
算法·语音识别
讳疾忌医丶7 小时前
深度拆解 RocksDB 内核:基于 C++17 的 FIFO 调度状态机与温度阶梯自愈设计
java·c++·算法·架构
高亦真7 小时前
今天是学习嵌入式的第37天
linux·学习·算法
罗西的思考9 小时前
[Agent Memory / 强化学习] MemPO源码学习笔记 --- (2)--- 训练
人工智能·算法·机器学习
深圳市方中禾科技10 小时前
FZH1625 LCD 驱动芯片深度评测与实战指南
算法·led
我不会起名字32211 小时前
一天一道算法题(34):回溯法的经典例题(子集)
java·数据结构·python·算法·golang·深度优先·力扣
huang57914712 小时前
哈希算法的抗碰撞机制与安全性增强策略4
算法
林浩杨_13 小时前
SIGIR 2026|南京大学:Video-GAR:“通过生成 Query 来验证视频语义理解”的生成增强范式
论文阅读·人工智能·算法
Elsa️74613 小时前
算法一周刷题总结
c++·算法
小小程序猴114 小时前
深圳乘路资讯AI培训怎么样?课程靠谱吗?——一套课程可信度评估模型与实证分析
人工智能·算法