【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 <= 2000s仅由小写英文字母组成
解题方法:动态规划
创建一个动态规划数组f,其中f[i]表示前i个字符中能选择的k回文子字符串的最大数目。
那么显然,对于f[i],我们有两种选择:
- 不选择以
s[i-1]结尾的回文子字符串,那么f[i] = f[i-1]。 - 选择以
s[i-1]结尾的回文子字符串,那么我们需要找到一个长度至少为k的回文子字符串[j, i),那么f[i] = f[j] + 1。
对于第二种情况,我们有必要从 k k k、 k + 1 k+1 k+1、 k + 2 k+2 k+2、...、 i i i都试试吗?没有。最多试一下 k k k和 k + 1 k+1 k+1保证奇数长度和偶数长度两种情况都考虑过就好了。
因为站在整体角度,如果存在 k + 2 k+2 k+2长的回文串的话, k k k长度也一定是回文串,没必要选 k + 2 k+2 k+2长。所以我们只需要考虑长度为 k k k和 k + 1 k+1 k+1的回文串。
- 时间复杂度 O ( N 2 ) O(N^2) O(N2)
- 空间复杂度 O ( N log N ) O(N\log N) O(NlogN)
AC代码
C++
cpp
/*
* @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和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~
千篇源码题解已开源