刷题之动态规划-回文串

前言

大家好,我是jiantaoyab,开始刷动态规划的回文串类型相关的题目

动态规划5个步骤

  1. 状态表示 :dp数组中每一个下标对应值的含义是什么>dp[i]表示什么
  2. 状态转移方程: dp[i] 等于什么
  3. 1 和 2 是动态规划的核心步骤,第三步是初始化,保证填表的时候不越界
  4. 填表顺序:为了保证填写当前状态的时候,所需要的状态已经计算过
  5. 返回值

回文子串

image-20240408083127417

题目分析

image-20240408091944564

代码

class Solution {
public:
    int countSubstrings(string s) {
      int n = s.size();
      int ret = 0;
      vector<vector<bool>> dp(n, vector<bool>(n));
      for(int i = n - 1; i >= 0; i--)
      {
        for(int j = i; j < n; j++) // i <= j
        {
          if(s[i] == s[j]) 
             dp[i][j] =  i + 1 < j ? dp[i + 1][j - 1] : true;
          if(dp[i][j]) ret++;
          
        }
      }

      return ret;
    }
};

最长回文子串

image-20240408093514656

代码

动态规划版本

class Solution {
public:
    string longestPalindrome(string s) {
        int n = s.size();
        vector<vector<bool>> dp(n, vector<bool>(n));
        int len = 1, begin = 0;
        for(int i = n - 1; i >= 0; i--)
        {
          for(int j = i; j < n; j++)
          {
            if(s[i] == s[j]) dp[i][j] = i + 1 < j ? dp[i + 1][j - 1] : true;
            if(dp[i][j] && j - i + 1 > len)
            {
               len = j - i + 1;
               begin = i;
               
            }
           
          }
        }
        return s.substr(begin, len);
    }
};

中心探测法

image-20240408101013524

class Solution {
public:
    string longestPalindrome(string s) {
     string RetStr="";
     for(int i=0;i<s.size();i++)
     {
         //回文串为奇数
         int left=i-1;
         int right=i+1;
         while(left>=0&&right<s.size()&&s[left]==s[right])
         {
             left--;
             right++;
         }
         if(RetStr.size()<right-left-1)
         {
             //babad
             //01234  letf=-1 i=1  right=3
             RetStr=s.substr(left+1,right-left-1);
         }
        //回文串为偶数
         left=i;
         right=i+1;
           while(left>=0&&right<s.size()&&s[left]==s[right])
         {
             left--;
             right++;
         }
          if(RetStr.size()<right-left-1)
         {
             
             RetStr=s.substr(left+1,right-left-1);
         }

     }
        return RetStr;
    }
};

分割回文串 IV

image-20240408101159072

代码

class Solution {
public:
    bool checkPartitioning(string s) {
      int n = s.size();
      vector<vector<bool>> dp(n, vector<bool>(n));
      int count = 0;
      for(int i = n - 1; i>= 0; i--)
      {
        for(int j = i; j < n; j++)
        {
          if(s[i] == s[j] ) dp[i][j] = i + 1 < j ? dp[i + 1][j - 1] : true;
        
        }
      }

      //枚举第二个字符串的起始位置和结束位置
      for(int i = 1; i < n - 1; i++) //前后留一个字符给第一个字符串
      {
        for(int j = i; j < n - 1; j++)//结束位置从i开始到n - 1
        {
            if(dp[0][i - 1] && dp[i][j] && dp[j + 1][n - 1] ) return true;
        }
      }
      return false;
    }
};

分割回文串 II

image-20240409162018368

题目分析

image-20240409165941296

代码

class Solution {
public:
    int minCut(string s) {
      int n = s.size();
      vector<vector<bool>> is_pal(n, vector<bool>(n));
      int ret = 0;
      //把所有子串是不是回文串放到is_pal中
      for(int i = n - 1; i >= 0; i--)
      {
        for(int j = i; j < n; j++)
        {
          if(s[i] == s[j]) is_pal[i][j] = i + 1 < j ? is_pal[i + 1][j - 1] : true;
        }
      }
      vector<int> dp(n, INT_MAX);
      for(int i = 0; i < n; i++)
      {
        if(is_pal[0][i]) dp[i] = 0;
        // [0, i] 不是回文串
        else
        {
          for(int j = 1; j <= i; j++)
          {
            if(is_pal[j][i]) dp[i] = min(dp[i], dp[j - 1] + 1);
          }
        }
      }
      return dp[n - 1];
    }
};

最长回文子序列

image-20240410080452774

题目分析

image-20240410083625603

代码

class Solution {
public:
    int longestPalindromeSubseq(string s) {
      int n = s.size();
      vector<vector<int>> dp(n, vector<int>(n));
      //填表从下到上,左到右填
      for(int i = n - 1; i >= 0; i--)
      {
        dp[i][i] = 1; // i == j
        for(int j = i + 1; j < n; j++)
        {
          if(s[i] == s[j])
          {
            if(i + 1 == j) dp[i][j] = 2;
            else if(i + 1 < j) dp[i][j] = dp[i + 1][j - 1] + 2;
          }
          else
          {
            dp[i][j] = max(dp[i][j - 1], dp[i + 1][j]);
          }

        }
      }
      return dp[0][n - 1];
    }
};

让字符串成为回文串的最少插入次数

image-20240410084528577

题目分析

image-20240410085752956

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

相关推荐

  1. LeetCode---

    2024-04-13 22:50:02       17 阅读
  2. LeetCode 1745.分割IV(动态规划

    2024-04-13 22:50:02       31 阅读
  3. 【算法】分割动态规划】【回溯】

    2024-04-13 22:50:02       36 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-13 22:50:02       19 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-13 22:50:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-13 22:50:02       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-13 22:50:02       20 阅读

热门阅读

  1. Go语言并发编程(三)——初窥管道

    2024-04-13 22:50:02       16 阅读
  2. 【LeetCode热题100】45. 跳跃游戏 II(贪心)

    2024-04-13 22:50:02       17 阅读
  3. C# WPF故障记录

    2024-04-13 22:50:02       15 阅读
  4. 【00150】金融理论与实务-2023年4月自考真题

    2024-04-13 22:50:02       15 阅读
  5. 设计模式-里氏替换原则

    2024-04-13 22:50:02       17 阅读
  6. PyTorch 中的【高级索引】 或 【花式索引】

    2024-04-13 22:50:02       16 阅读
  7. 【图论】链式前向星实现图的BFS搜索

    2024-04-13 22:50:02       13 阅读
  8. Soulver v3.10.3.1 mac版 智能文本计算器 兼容 M1/M2/M3

    2024-04-13 22:50:02       21 阅读
  9. Ant Design Vue Table 自定义渲染与自定义单元格

    2024-04-13 22:50:02       13 阅读
  10. 【LeetCode刷题记录】76. 最小覆盖子串

    2024-04-13 22:50:02       10 阅读
  11. dfs板子

    dfs板子

    2024-04-13 22:50:02      11 阅读
  12. 蓝桥杯 2021 省 AB 2 洛谷P8755 负载均衡

    2024-04-13 22:50:02       17 阅读