- 打卡等级:初来乍到
- 打卡总天数:5
- 打卡月天数:5
- 打卡总奖励:35
- 最近打卡:2025-07-13 16:05:02
VIP
- 积分
- 10018
|
一、问题分析 这道题目要求我们计算将数字字符串分割成k个子串的"**分割"方式数目。**分割需要满足三个条件: 分成k段互不相交的子串 每个子串长度至少为minLength 每个子串首字符是质数(2,3,5,7),尾字符是非质数(1,4,6,8,9)
二、解题思路我们可以使用动态规划来解决这个问题: 三、C++代码实现
- class Solution {
- public:
- int beautifulPartitions(string s, int k, int minLength) {
- const int MOD = 1e9 + 7;
- int n = s.size();
- // 预处理质数判断
- auto isPrime = [](char c) {
- return c == '2' || c == '3' || c == '5' || c == '7';
- };
- // 检查首尾字符是否满足条件
- if (!isPrime(s[0]) || isPrime(s.bACk())) return 0;
- // dp[i][j]表示前i个字符分成j段的方案数
- vector<vector<int>> dp(n + 1, vector<int>(k + 1, 0));
- dp[0][0] = 1;
- for (int j = 1; j <= k; ++j) {
- // 前缀和优化,避免重复计算
- vector<int> prefix(n + 1, 0);
- prefix[0] = dp[0][j - 1];
- for (int i = 1; i <= n; ++i) {
- prefix[i] = (prefix[i - 1] + dp[i][j - 1]) % MOD;
- }
- for (int i = 1; i <= n; ++i) {
- if (i < minLength) continue;
- if (!isPrime(s[i - 1]) && (i == n || isPrime(s[i]))) {
- int start = max(0, i - minLength);
- dp[i][j] = (dp[i][j] + prefix[start]) % MOD;
- }
- }
- }
- return dp[n][k];
- }
- };
复制代码
四、代码详解预处理阶段:
动态规划表初始化:
填充dp表:
外层循环遍历分割段数j 内层循环遍历字符串长度i 检查分割点是否满足条件
结果返回:
五、算法优化前缀和优化:
使用prefix数组避免重复计算,将 时间复杂度从O(n^2k)优化到O(nk)
提前终止条件:
六、、扩展思考掌握这种动态规划解法,能够帮助你解决许多类似的字符串分割和组合问题! 来源:力扣2478题解:动态规划解决字符串**分割问题
|
|