当前位置: 首页 > news >正文

【Day40 LeetCode】动态规划DP 回文子串问题

一、动态规划DP 回文子串问题

1、回文子串 647

dp数组如果采用一维的,很难进行推导。采用二维,一开始的想法是dp[i][j]表示s[i]~s[j]之间回文子串的个数,这样发现在推导递推公式时遇到困难,例如在s[i]==s[j]时,不知道s[i+1:j-1]是否是回文子串。所以这样的定义不合理,所以让dp[i][j]表示s[i:j]是否是回文子串就好。
这样递推公式就好推导,当s[i]==s[j],如果j-i<=2,则dp[i][j] = 1,否则dp[i][j] = dp[i+1][j-1];当s[i]!=s[j],dp[i][j] = 0。再在循环里累加这个dp[i][j]就是所有的回文子串数量。
另外,关于遍历顺序需要提一下,递推公式dp[i][j] = dp[i+1][j-1],则需要提前知道dp[i+1][j-1],所以i应该是逆序,j正序。

class Solution {
public:
    int countSubstrings(string s) {
        int n = s.size();
        vector<vector<int>> dp(n, vector<int>(n, 0));
        int ans = 0;
        for(int i=n-1; i>=0; --i){
            for(int j=i; j<n; ++j){
                if(s[i] == s[j] && (j-i<=2 || dp[i+1][j-1])){
                    dp[i][j] = 1;
                    ++ans;
                }
            }
        }
        return ans;
    }
};

这题更优的解法是采用双指针,能把空间复杂度优化到O(1)。有一个元素为中心点和两个元素为中心点两种情况

class Solution {
    int extend(const string &s, int i, int j){
        int ans = 0;
        while(i>=0 && j<s.size() && s[i--]==s[j++])
            ++ans;
        return ans;
    }
public:
    int countSubstrings(string s) {
        int ans = 0;
        for(int i=0; i<s.size(); ++i){
            ans += extend(s, i, i);
            ans += extend(s, i, i+1);
        }
        return ans;
    }
};

2、最长回文子序列 516

这题和上一题很相似,只不过由回文子串变成回文子序列。代码如下:

class Solution {
public:
    int longestPalindromeSubseq(string s) {
        int n = s.size();
        vector<vector<int>> dp(n, vector<int>(n));
        for(int i=0; i<n; ++i)
            dp[i][i] = 1;
        for(int i=n-2; i>=0; --i){
            for(int j=i+1; j<n; ++j){
                if(s[i]==s[j] && (dp[i+1][j-1] || j-i==1)){
                    dp[i][j] = 2 + dp[i+1][j-1];
                }else{
                    dp[i][j] = max(dp[i+1][j], dp[i][j-1]);
                }
            }
        }
        return dp[0][n-1];
    }
};

二、写在后面

回文子串采用二维dp数组比较好理解,比较经典的转移关系是 d p [ i ] [ j ] = d p [ i + 1 ] [ j − 1 ] dp[i][j] = dp[i+1][j-1] dp[i][j]=dp[i+1][j1]相似的形式,i逆序遍历,j正序遍历$。

相关文章:

  • 如何在微信小程序中使用 Lottie 动画
  • 机器学习 网络安全
  • Hadoop 简介及其hdfs常用命令
  • LPDDR4、LPDDR5物理结构和信号定义区别
  • UniApp 的页面结构是怎样的?
  • 最新国内 ChatGPT Plus/Pro 获取教程
  • 【免费送书活动】《MySQL 9从入门到性能优化(视频教学版)》
  • 使用时间盲注与布尔盲注获取数据库名,表名及列名
  • 深度剖析观察者模式:从理论到实战的Java实现
  • 基于IOS实现各种倒计时功能
  • Linux udp poll函数
  • 行内元素和块级元素
  • New Game--(单调队列)
  • 如何设置linux系统时间?
  • USART串口协议
  • Java知识速记:Exception与Error的区别
  • c++:STL介绍
  • Rank-Analysis 预组队识别(英雄联盟)
  • Qwen2-VL 的重大省级,Qwen 发布新旗舰视觉语言模型 Qwen2.5-VL
  • Flask和Django相比哪个更适合新手?
  • 甘肃省铁路投资建设集团有限公司网站/东营seo网站推广
  • 如何防止网站被劫持/外链收录网站
  • 如何在网上推广app/seo站外推广有哪些
  • 满城住房和城乡建设局网站/百度人工智能开放平台
  • 乌鲁木齐疫情最新消息/无锡网络优化推广公司
  • 徐州网站建设多少钱/湖北网站推广