Number of Beautiful Partitions

Number of Beautiful Partitions

You are given a string s that consists of the digits '1' to '9' and two integers k and minLength.

A partition of s is called beautiful if:

  • s is partitioned into k non-intersecting substrings.
  • Each substring has a length of at least minLength .
  • Each substring starts with a prime digit and ends with a non-prime digit. Prime digits are '2' , '3' , '5' , and '7' , and the rest of the digits are non-prime.

Return the number of beautiful partitions of s . Since the answer may be very large, return it modulo 109+7.

A substring is a contiguous sequence of characters within a string.

Example 1:

Input: s = "23542185131", k = 3, minLength = 2
Output: 3
Explanation: There exists three ways to create a beautiful partition:
"2354 | 218 | 5131"
"2354 | 21851 | 31"
"2354218 | 51 | 31"

Example 2:

Input: s = "23542185131", k = 3, minLength = 3
Output: 1
Explanation: There exists one way to create a beautiful partition: "2354 | 218 | 5131".

Example 3:

Input: s = "3312958", k = 3, minLength = 1
Output: 1
Explanation: There exists one way to create a beautiful partition: "331 | 29 | 58".

Constraints:

1k,minLengths.length1000
s consists of the digits '1' to '9' .

 

解题思路

  这题很容易想到动态规划,不过如果直接暴力dp的话会超时,因此还需要进行优化,比赛的时候调了1个多小时都没有调出来,说白了就是不熟练。

  定义状态f(i,j)表示所有从前i字符中分成j组的合法方案的数量。状态转移方程就是f(i,j)=u=len×(j1)+1ilen+1f(u1,j1)其中要保证si不为质数,并且su要为质数。u是第j组的左端点,i是第j组的右端点。

  因此就很容易写出TLE代码,时间复杂度为O(n2×k)

复制代码
 1 class Solution {
 2 public:
 3     int mod = 1e9 + 7;
 4     
 5     int beautifulPartitions(string s, int k, int minLength) {
 6         int n = s.size();
 7         vector<vector<int>> f(n + 1, vector<int>(k + 1));
 8         f[0][0] = 1;
 9         unordered_set<int> st({2, 3, 5, 7});
10         for (int i = 1; i <= n; i++) {
11             if (!st.count(s[i - 1] - '0')) {
12                 for (int j = 1; j <= k; j++) {
13                     for (int u = minLength * (j - 1) + 1; u + minLength - 1 <= i; u++) {
14                         if (st.count(s[u - 1] - '0')) f[i][j] = (f[i][j] + f[u - 1][j - 1]) % mod;
15                     }
16                 }
17             }
18         }
19         return f[n][k];
20     }
21 };
复制代码

  现在就要对其进行优化,对于第3个循环,可以发现如果我们固定j不变,而每次增加i,那么u的枚举范围[len×(j1)+1,ilen+1]的左端点总是固定不变的,而右端点每次会加1,这意味着我们总是重复枚举前面的固定不变的部分,因此我们可以考虑开个变量cnt来累加前面固定的部分,这样就不用每次从头开始枚举了。当时比赛就是卡在cnt所要累加的值。其实看状态转移方程就可以发现,f(i,j)每次都是加上f(u1,j1),而第一维是变化的量,对比于i1,当枚举到i时就只多加了一个f(i+1len+1,j1)。因此当枚举到icnt就累加f(ilen+1,j1)就可以了(前提是silen+1为质数)。关键是要看到前后两次是哪个量发生了变化。

  AC代码如下,时间复杂度为O(n×k)

复制代码
 1 class Solution {
 2 public:
 3     int mod = 1e9 + 7;
 4 
 5     int beautifulPartitions(string s, int k, int minLength) {
 6         int n = s.size();
 7         vector<vector<int>> f(n + 1, vector<int>(k + 1));
 8         f[0][0] = 1;
 9         unordered_set<int> st({2, 3, 5, 7});
10         for (int j = 1; j <= k; j++) {
11             int cnt = 0;
12             for (int i = minLength * j; i <= n; i++) {
13                 if (st.count(s[i - minLength] - '0')) cnt = (cnt + f[i - minLength][j - 1]) % mod;
14                 if (!st.count(s[i - 1] - '0')) f[i][j] = cnt;
15             }
16         }
17         return f[n][k];
18     }
19 };
复制代码

  当然,可以改变ij的枚举顺序,这里就定义f(j,i)表示所有从前i字符中分成j组的合法方案的数量(和上面的定义一样),这种写法会比上面的快一些(涉及到底层)。

  AC代码如下:

复制代码
 1 class Solution {
 2 public:
 3     int mod = 1e9 + 7;
 4 
 5     int beautifulPartitions(string s, int k, int minLength) {
 6         int n = s.size();
 7         vector<vector<int>> f(k + 1, vector<int>(n + 1));
 8         f[0][0] = 1;
 9         unordered_set<int> st({2, 3, 5, 7});
10         for (int j = 1; j <= k; j++) {
11             int cnt = 0;
12             for (int i = minLength * j; i <= n; i++) {
13                 if (st.count(s[i - minLength] - '0')) cnt = (cnt + f[j - 1][i - minLength]) % mod;
14                 if (!st.count(s[i - 1] - '0')) f[j][i] = cnt;
15             }
16         }
17         return f[k][n];
18     }
19 };
复制代码
posted @   onlyblues  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
Web Analytics
点击右上角即可分享
微信分享提示