动态规划Day34:回文

647. 回文子串

DP 数组定义 :dp[i][j] 表示字符串 s 中,下标从 i 到 j 的子串 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] 已被计算),j 从 i 往后遍历(只处理 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 中,下标 i 到 j 区间内的最长回文子序列长度。

状态转移:

  • 若 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] 已计算),j 从 i 往后遍历;

  • 每次更新 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;
    }
相关推荐
UIU1143 小时前
P1233 [ICPC 2001 Taejon R] 木棍加工
数据结构·c++·算法·动态规划
论文复现现场3 小时前
WRF、FEA 能用 L40S 加速吗?求解器检查、断点恢复与长期运行
java·数据库·算法·wrf·有限元分析·gpu计算·断点续算
ZhengEnCi3 小时前
用 AI 写代码为什么拼到最后还是拼人:算力瓶颈与领域专家提示词的本质差异
算法·架构
秋天的怀念_David4 小时前
第二十一夜 · 数字黑洞与西西弗斯的惩罚
java·程序人生·算法
碧海银沙音频科技研究院5 小时前
在PC电脑上用Whisper→Marian算法实现离线语音翻译功能
算法·whisper
niyongsheng5 小时前
3D 装箱算法工程化:数据结构、放置启发式与支撑规则
数据结构·算法·rust
j7~8 小时前
【穷举、深搜与回溯算法】一棵决策树讲透全排列与子集
数据结构·c++·算法·leetcode·回溯·递归
傅科摆 _ py9 小时前
DP,贪心,堆和栈,二分力扣复习
开发语言·python·算法
Shaoshing9 小时前
LeetCode100 42.接雨水
java·算法·leetcode
域限奇点访客10 小时前
用AI生成问卷的网站怎么选?看题目录入结构、题型映射和生成后的校验
算法