计算一共有多少种移除方案可以使s变为回文串
创始人
2024-03-19 23:30:58
0

问题描述:

        对于一个字符串, 从前开始读和从后开始读是一样的, 我们就称这个字符串是回文串。例如"ABCBA","AA", "A" 是回文串, 而"ABCD", "AAB"不是回文串。牛牛特别喜欢回文串, 他手中有一个字符串s, 牛牛在思考能否从字 符串中移除部分(0个或多个)字符使其变为回文串,并且牛牛认为空串不是回文串。牛牛发现移除的方案可能有很多种, 希望你来帮他计算一下一共有多少种移除方案可以使s变为回文串。对于两种移除方案, 如果移除的字符依次构成的序列不一样就是不同的方案。
例如,XXY 4种 ABA 5种
【说明】 这是今年的原题,提供的说明和例子都很让人费解。现在根据当时题目的所有测试用例,重新解释当时的题目 含义:

1)"1AB23CD21",你可以选择删除A、B、C、D,然后剩下子序列{1,2,3,2,1},只要剩下的子序列是同一个,那 么就只算1种方法,和A、B、C、D选择什么样的删除顺序没有关系。

2)"121A1",其中有两个{1,2,1}的子序列,第一个{1,2,1}是由{位置0,位置1,位置2}构成,第二个{1,2,1} 是由{位置0,位置1,位置4}构成。这两个子序列被认为是不同的子序列。也就是说在本题中,认为字面值一样 但是位置不同的字符就是不同的。

3)其实这道题是想求,str中有多少个不同的子序列,每一种子序列只对应一种删除方法,那就是把多余的东西去掉,而和去掉的顺序无关。
4)也许你觉得我的解释很荒谬,但真的是这样,不然解释不了为什么,XXY 4种 ABA 5种,而且其他的测试用例都印证了这一点。

思想:

        本题是范围上的尝试模型。

        使用动态规划的思想进行解题。定义二维数组dp[i][j],行列分别用字符串str的字符表示,二维数组dp[i][j]的含义是:字符串从i开始到j结尾子序列是回文串有几种方案数。

        二维数的左下部分不需要填写。

        二维数组对角线dp[i][i]全部填一。紧挨着对角线的右上对角线dp[i][i+1]表示字符串从第i个字符到第j=i+1个字符是回文串有几种方案数,我们很容易知道如果str[i]==str[i+1]那么有三种可能方案,否则为两种可能方案。

        对于二维数组的其他位置dp[L][R],有如下几种可能性:

  1. 若L位置和R位置都不在最后的回文字符串中,设该可能性结果为a。
  2. 若L位置在和R位置都不在最后的回文字符串中,设该可能性结果为b。
  3. 若L位置不在和R位置都在最后的回文字符串中,设该可能性结果为d。
  4. 若L位置和R位置都在最后的回文字符串中,隐含的条件是str[L]==str[R],设该可能性结果为d。

         这四种情况是相互互斥的,dp[L][R] = a + b + c + d (情况4成立)  或者 dp[i][j] = a + b + c (情况4不成立)。

        dp[L+1][R]表示L位置不在最后的回文字符串中的方法数,其结果为a + c。

        dp[L][R-1]表示R位置不在最后的回文字符串中的方法数,其结果为a + b。

        dp[L+1][R-1]表示L和R位置都不在最后的回文字符串中的方法数,其结果为a。

        综合上述: a+ b + c =  dp[L+1][R] + dp[L][R-1] -  dp[L+1][R-1] 。

        现在就剩下d的值未算出,有d可能新结果说明str[L]==str[R]条件成立。字符串中两端的字符固定中间字符串是回文串有几种方案数为a,此时我们需要格外注意还有一种可能性就是中间字符串字符全部删除,所以d = a + 1 。

代码:

    public static int way(String str) {char[] s = str.toCharArray();int n = s.length;int[][] dp = new int[n][n];for (int i = 0; i < n; i++) {dp[i][i] = 1;}for (int i = 0; i < n - 1; i++) {dp[i][i + 1] = s[i] == s[i + 1] ? 3 : 2;}for (int L = n - 3; L >= 0; L--) {for (int R = L + 2; R < n; R++) {dp[L][R] = dp[L + 1][R] + dp[L][R - 1] - dp[L + 1][R - 1];if (s[L] == s[R]) {dp[L][R] += dp[L + 1][R - 1] + 1;}}}return dp[0][n - 1];}public static void main(String[] args) {System.out.println(way("ABA"));System.out.println(way("XXY"));}

相关内容

热门资讯

AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...
AWR报告解读 WORKLOAD REPOSITORY PDB report (PDB snapshots) AW...
群晖外网访问终极解决方法:IP... 写在前面的话 受够了群晖的quickconnet的小水管了,急需一个新的解决方法&#x...