统计不同回文子字符串--LeetCode730:分析清晰

2024-06-02 15:38

本文主要是介绍统计不同回文子字符串--LeetCode730:分析清晰,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 

统计不同回文子字符串–LeetCode730

题目

给定一个字符串 S,找出 S 中不同的非空回文子序列个数,并返回该数字与 10^9 + 7的模。通过从 S 中删除 0 个或多个字符来获得子字符序列。如果一个字符序列与它反转后的字符序列一致,那么它是回文字符序列。如果对于某个 iA_i != B_i,那么 A_1, A_2, ...和 B_1, B_2, ...这两个字符序列是不同的。

示例 1:

输入:
S = 'bccb'
输出:6
解释:
6 个不同的非空回文子字符序列分别为:'b', 'c', 'bb', 'cc', 'bcb', 'bccb'。
注意:'bcb' 虽然出现两次但仅计数一次。

示例 2:

输入:
S = 'abcdabcdabcdabcdabcdabcdabcdabcddcbadcbadcbadcbadcbadcbadcbadcba'
输出:104860361
解释:
共有 3104860382 个不同的非空回文子字符序列,对 10^9 + 7 取模为 104860361。

提示:

  • 字符串 S 的长度将在[1, 1000]范围内。
  • 每个字符 S[i] 将会是集合 {‘a’, ‘b’, ‘c’, ‘d’} 中的某一个。

思路

状态定义:dp[i][j]表示s[i, j]中回文子序列的个数。

转移方程:

  • 如果s[i] != s[j],则有dp[i][j] = dp[i][j - 1] + dp[i + 1][j] - dp[i + 1][j - 1]dp[i + 1][j - 1]dp[i][j - 1]dp[i+1][j]中都有,所以要减去一个。
  • 如果s[i] = s[j] = c,则有dp[i][j] = 2 * dp[i + 1][j - 1],乘以2意思是在s[i + 1, j - 1]中所有的回文子序列两边加上c,就构成了新的回文子序列,原来有dp[i + 1][j - 1]这么多个,两边加上c之后增加了dp[i + 1][j - 1]个回文子序列,所以乘以2得到当前的dp[i][j]

但是上述s[i] = s[j]情况下,结果存在重复计算和疏漏,需要进行去重和补充。

  • 如果在s[i + 1, j - 1]没有字符c,需要进行补充,即dp[i][j] += 2,补上的是[c], [c, c];
  • 如果在s[i + 1, j - 1]只有一个字符c,需要进行补充,即dp[i][j] += 1,补上的是[c, c];
  • 如果在s[i + 1, j - 1]有两个或多个字符c,需要进行去重,即dp[i][j] -= dp[l + 1][r - 1]li的左边第一个字符为c的位置, rj的右边第一个字符为c的位置。

初始条件:

  • dp[n - 1][n - 1] = 1表示单个字符就是一个回文子序列
  • dp[i][i - 1] = 0表示字符串为空

最终答案就是dp[0][n-1]

参考题解:
阿飞的题解
想想大司马会怎么做的题解

代码如下(用时69ms):

class Solution {public int countPalindromicSubsequences(String S) {if (S == null || S.length() == 0) {return 0;}int n = S.length();int mod = 1000000000+7;int[][] dp = new int[n][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.charAt(i) == S.charAt(j)) {dp[i][j] = 2*dp[i+1][j-1];int left = i+1;int right = j-1;while (left <= right && S.charAt(i) != S.charAt(left)) left++;while (left <= right && S.charAt(j) != S.charAt(right)) right--;if (left > right) {dp[i][j] += 2;} else if (left == right) {dp[i][j] += 1;} else {dp[i][j] -= dp[left+1][right-1];}}else {dp[i][j] = dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1];}dp[i][j] = (dp[i][j] < 0) ? dp[i][j]+mod : dp[i][j]%mod;}}return dp[0][n-1];}
}

这篇关于统计不同回文子字符串--LeetCode730:分析清晰的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1024385

相关文章

笔记本电脑屏幕模糊?6招恢复屏幕清晰!

在数字化时代的浪潮中,笔记本电脑已成为我们生活、学习和工作中不可或缺的一部分。然而,当那曾经清晰明亮的屏幕逐渐变得模糊不清时,无疑给我们的使用体验蒙上了一层阴影。屏幕模糊不仅影响视觉舒适度,更可能对我们的工作效率和眼睛健康构成威胁。 遇到笔记本电脑屏幕模糊的情况时我们应该如何解决?本文将与大家分享6个简单易懂的解决方法。 方法一:调整Windows分辨率 电脑屏幕模糊显示不清晰怎

[职场] 公务员的利弊分析 #知识分享#经验分享#其他

公务员的利弊分析     公务员作为一种稳定的职业选择,一直备受人们的关注。然而,就像任何其他职业一样,公务员职位也有其利与弊。本文将对公务员的利弊进行分析,帮助读者更好地了解这一职业的特点。 利: 1. 稳定的职业:公务员职位通常具有较高的稳定性,一旦进入公务员队伍,往往可以享受到稳定的工作环境和薪资待遇。这对于那些追求稳定的人来说,是一个很大的优势。 2. 薪资福利优厚:公务员的薪资和

2390.从字符串中移除星号

给你一个包含若干星号 * 的字符串 s 。 在一步操作中,你可以: 选中 s 中的一个星号。 移除星号左侧最近的那个非星号字符,并移除该星号自身。 返回移除 所有 星号之后的字符串。 注意: 生成的输入保证总是可以执行题面中描述的操作。 可以证明结果字符串是唯一的。 示例 1: 输入:s = “leet**cod*e” 输出:“lecoe” 解释:从左到右执行移除操作: 距离第 1 个

Python 字符串占位

在Python中,可以使用字符串的格式化方法来实现字符串的占位。常见的方法有百分号操作符 % 以及 str.format() 方法 百分号操作符 % name = "张三"age = 20message = "我叫%s,今年%d岁。" % (name, age)print(message) # 我叫张三,今年20岁。 str.format() 方法 name = "张三"age

SQL Server中,查询数据库中有多少个表,以及数据库其余类型数据统计查询

sqlserver查询数据库中有多少个表 sql server 数表:select count(1) from sysobjects where xtype='U'数视图:select count(1) from sysobjects where xtype='V'数存储过程select count(1) from sysobjects where xtype='P' SE

高度内卷下,企业如何通过VOC(客户之声)做好竞争分析?

VOC,即客户之声,是一种通过收集和分析客户反馈、需求和期望,来洞察市场趋势和竞争对手动态的方法。在高度内卷的市场环境下,VOC不仅能够帮助企业了解客户的真实需求,还能为企业提供宝贵的竞争情报,助力企业在竞争中占据有利地位。 那么,企业该如何通过VOC(客户之声)做好竞争分析呢?深圳天行健企业管理咨询公司解析如下: 首先,要建立完善的VOC收集机制。这包括通过线上渠道(如社交媒体、官网留言

气象站的种类和应用范围可以根据不同的分类标准进行详细的划分和描述

气象站的种类和应用范围可以根据不同的分类标准进行详细的划分和描述。以下是从不同角度对气象站的种类和应用范围的介绍: 一、气象站的种类 根据用途和安装环境分类: 农业气象站:专为农业生产服务,监测土壤温度、湿度等参数,为农业生产提供科学依据。交通气象站:用于公路、铁路、机场等交通场所的气象监测,提供实时气象数据以支持交通运营和调度。林业气象站:监测林区风速、湿度、温度等气象要素,为林区保护和

LeetCode--234 回文链表

题目 请判断一个链表是否为回文链表。 示例 示例 1:输入: 1->2输出: false示例 2:输入: 1->2->2->1输出: true /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val

LeetCode--214 最短回文串

题目 给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串。找到并返回可以用这种方式转换的最短回文串。 示例 示例 1:输入: "aacecaaa"输出: "aaacecaaa"示例 2:输入: "abcd"输出: "dcbabcd" 思路: 我们需要添加多少个字符与给定字符串的前缀子串回文的长度有关. 也就是说去掉其前缀的回文子串,我们只需要补充剩下的子串的逆序

剑指offer(C++)--左旋转字符串

题目 汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它! class Solution {public:string LeftRotateStri