首页 > 其他分享 >动态规划-回文串

动态规划-回文串

时间:2022-11-01 14:34:59浏览次数:59  
标签:字符 int 字符串 序列 动态 规划 dp 回文

回文串是从左到右和从右到左读起来一样的字符串,变种还有回文子序列,区别就是字符可以不连续。

求回文串个数、最长回文串、最长回文序列也是典型的二维动态规划问题。

我们通过几个简单的案例看一下这些题目的规律。

案例1:给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。

子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。

首先我们要明白:

①单个字符串肯定是回文串,

②两个字符,如果相同也是回文串

③超过三个字符序列的情况,如果最前最后两个字符相同,回文序列的长度就可以在去掉最前最后两个字符的回文序列+2

④如果最前最后两个字符串不相同,我们只好退其次,求解dp[i +1][j], dp[i][j - 1]两个的较大值

我们定义dp[i][j]为字符串中从i到j的最长回文子序列的长度,显而易见,dp[i][i]是回文的。

当s[i]==s[j]时,有dp[i][j] = dp[i + 1][j - 1] + 2

当s[i]!=s[j]时,有dp[i][j] = max{dp[i +1][j], dp[i][j - 1]}

我们要求的最终值就是dp[0][n-1]

为了保证求解当前问题是所有子问题已经求解,需要考虑遍历的顺序。

首先:因为i<=j,所有我们只需要求解上三角矩阵的值即可。

     
i,j-1 i,j  
  i+1,j  

注意观察dp[i][j]的子问题,一个在自己的下方格子,一个在自己的左边格子,

也就是说我们的每一行的遍历要从下到上,每一列的遍历要从左到右。

  public int longestPalindromeSubseq(String s) {
        int n = s.length();
        int[][] dp = new int[n][n];

        for (int i = n - 1; i >= 0; i--) {
            //单个字符是回文的,长度为1
            dp[i][i] = 1;
            for (int j = i + 1; j < n; j++) {
                if (s.charAt(i) == s.charAt(j)) {
                    dp[i][j] = dp[i + 1][j - 1] + 2;
                } else {
                    dp[i][j] = Math.max(dp[i +1][j], dp[i][j - 1]);
                }

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

案例2:给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。

这个题目要求回文串,跟上一题目是有区别的,回文串必须是连续的。

遍历顺序还是一样行从下到上,列从左到有。

回文串要求最前最后两个字符必须相同,且取掉最前最后两个字符的子串仍然是回文串

 public int countSubstrings(String s) {
        int n = s.length();
        boolean[][] dp = new boolean[n][n];
        int ans = 0;
        for (int i = n-1; i >=0; i--) {
            for (int j = i; j < n; j++) {//j-i==0,单字符是回文串,j-i=1两个字符相等也是回文串
                if (s.charAt(i) == s.charAt(j) && (j - i < 2 || dp[i + 1][j - 1])) {
                    dp[i][j] = true;
                    ans++;
                }
            }
        }
        return ans;
    }

留一个未解题目

案例3(5):给你一个字符串 s,找到 s 中最长的回文子串。

标签:字符,int,字符串,序列,动态,规划,dp,回文
From: https://www.cnblogs.com/wangbin2188/p/16847580.html

相关文章

  • 动态规划-公共子序列
    公共子序列是二维动态规划的典型问题,一般用了求两个字符串的相似程度。我们看一个案例:案例1:给定两个字符串 text1和 text2,返回这两个字符串的最长公共子序列的长度......
  • 动态规划-子序列
    子序列是序列的一部分,元素可以不连续。子串是字符串的一部分,必须连续。求子序列的和、连续递增子序列都是经典的一维动态规划问题。这一类题目都有差不多的思路,我们看案......
  • 关于数字孪生,有没有体系化的规划和实现途径?
    数字孪生就是物理实体数字空间的重构,也可以理解为虚拟化,我们在操作数字空间的对象时物理空间的实体对象相应动作,同样物理空间的实体发生状态变化,数字空间的对象相应发生改变......
  • 【QT】创建动态链接库及使用
    创建动态链接库创建一个项目选择library的C++库,下一步。选择共享库,输入动态库的名字,选择创建路径,下一步选择编译环境,下一步选择QTCore模块,该模块提供核心的非图......
  • node2_动态路径拼接错误问题
      如果使用相对路径,不在当前目录下通过其他目录来找到这个JS运行就会报错,当我们使用fs模块来操作文件时,我们如果使用相对路径的话,很容易出现路劲动态拼接错误的情况,......
  • vue动态绑定class的几种方式
    开发项目中:vue动态绑定class的几种方式~第一种:(最简单的绑定)1.绑定单个classhtml部分: <div:class="{'active':isActive}"></div>js部分:判断是否绑定一个activedat......
  • 动态规划-路径问题
    动态规划是一种通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法,常常适用于有重叠子问题和最优子结构性质的问题,并且记录所有子问题的结果,因此动态规划方法所......
  • c# 动态添加属性字段
    上来先吐槽一波,近一段时间公司为搞跨平台的客户端,我的wpf客户端逐渐被放弃,我的工作也越来越少,新的客户端采用qt来做,也有可能是qt开发进度太慢,项目比较紧,于是想让我的客......
  • js 如何给一个对象,动态添加属性字段
    第一种方法:无指定属性letobj={"name":"tom","age":16}letkey="id";letvalue=2obj[key]=value;console.log(obj)第二种方法,利用扩展运算符,简单又实用无......
  • cross socket ssl动态库
    crosssocketssl动态库crosssocket支持ssl需要动态库的支持,它的源码注释就说得很清楚。unitNet.OpenSSL;{OpenSSL下载:https://indy.fulgan.com/SSL/htt......