2472.不重叠回文子字符串的最大数目:动态规划(贪心)

【LetMeFly】2472.不重叠回文子字符串的最大数目:动态规划(贪心)

力扣题目链接:https://leetcode.cn/problems/maximum-number-of-non-overlapping-palindrome-substrings/

给你一个字符串 s 和一个 整数 k

从字符串 s 中选出一组满足下述条件且 不重叠 的子字符串:

  • 每个子字符串的长度 至少k
  • 每个子字符串是一个 回文串

返回最优方案中能选择的子字符串的 最大 数目。

子字符串 是字符串中一个连续的字符序列。

 

示例 1 :

输入:s = "abaccdbbd", k = 3
输出:2
解释:可以选择 s = "abaccdbbd" 中斜体加粗的子字符串。"aba" 和 "dbbd" 都是回文,且长度至少为 k = 3 。
可以证明,无法选出两个以上的有效子字符串。

示例 2 :

输入:s = "adbcda", k = 2
输出:0
解释:字符串中不存在长度至少为 2 的回文子字符串。

 

提示:

  • 1 <= k <= s.length <= 2000
  • s 仅由小写英文字母组成

解题方法:动态规划

创建一个动态规划数组f,其中f[i]表示前i个字符中能选择的k回文子字符串的最大数目。

那么显然,对于f[i],我们有两种选择:

  1. 不选择以s[i-1]结尾的回文子字符串,那么f[i] = f[i-1]
  2. 选择以s[i-1]结尾的回文子字符串,那么我们需要找到一个长度至少为k的回文子字符串[j, i),那么f[i] = f[j] + 1

对于第二种情况,我们有必要从$k$、$k+1$、$k+2$、…、$i$都试试吗?没有。最多试一下$k$和$k+1$保证奇数长度和偶数长度两种情况都考虑过就好了。

因为站在整体角度,如果存在$k+2$长的回文串的话,$k$长度也一定是回文串,没必要选$k+2$长。所以我们只需要考虑长度为$k$和$k+1$的回文串。

  • 时间复杂度$O(nk)$,其中$n=len(s)$
  • 空间复杂度$O(n)$

AC代码

C++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*
* @LastEditTime: 2026-09-15 17:07:03
*/
class Solution {
private:
bool ok(string& s, int l, int r) { // [l, r)
// len->i: 3->1 4->2 5->2 6->3
for (int i = 0; i < (r - l) / 2; i++) {
if (s[l + i] != s[r - i - 1]) {
return false;
}
}
return true;
}
public:
int maxPalindromes(string& s, int k) {
int n = s.size();
vector<int> f(n + 1);
for (int i = k; i <= n; i++) {
f[i] = f[i - 1];
if (ok(s, i - k, i)) {
f[i] = max(f[i], f[i - k] + 1);
}
if (i != k && ok(s, i - k - 1, i)) {
f[i] = max(f[i], f[i - k - 1] + 1);
}
}
return f.back();
}
};

同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~

千篇源码题解已开源


2472.不重叠回文子字符串的最大数目:动态规划(贪心)
https://blog.letmefly.xyz/2026/09/15/LeetCode 2472.不重叠回文子字符串的最大数目/
作者
发布于
2026年9月15日
许可协议