Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,19 @@ tags:

<!-- solution:start -->

### 方法一
### 方法一:记忆化搜索

我们设计一个函数 $\textit{dfs}(i, \textit{cur}, t)$ 表示当前处理到字符串 $s$ 的下标 $i$,当前前缀中已经包含的字符集合为 $\textit{cur}$,并且还可以修改 $t$ 次字符时,能够得到的最大分割数量。那么答案即为 $\textit{dfs}(0, 0, 1)$。

函数 $\textit{dfs}(i, \textit{cur}, t)$ 的执行逻辑如下:

1. 如果 $i \geq n$,说明已经处理完字符串 $s$,返回 1。
2. 计算当前字符 $s[i]$ 对应的位掩码 $v = 1 \ll (s[i] - 'a')$,并计算更新后的字符集合 $\textit{nxt} = \textit{cur} \mid v$。
3. 如果 $\textit{nxt}$ 中的位数超过 $k$,说明当前前缀已经包含超过 $k$ 个不同字符,我们需要进行一次分割,此时分割数量加 1,并递归调用 $\textit{dfs}(i + 1, v, t)$;否则,继续递归调用 $\textit{dfs}(i + 1, \textit{nxt}, t)$。
4. 如果 $t > 0$,说明我们还可以修改一次字符。我们尝试将当前字符 $s[i]$ 修改为任意一个小写字母(共 26 种选择),对于每个选择,计算更新后的字符集合 $\textit{nxt} = \textit{cur} \mid (1 \ll j)$,并根据是否超过 $k$ 个不同字符,选择相应的递归调用方式,更新最大分割数量。
5. 使用哈希表缓存已经计算过的状态,避免重复计算。

时间复杂度 $O(n \times |\Sigma| \times k)$,空间复杂度 $O(n \times |\Sigma| \times k)$。其中 $n$ 为字符串 $s$ 的长度,而 $|\Sigma|$ 为字符集大小。

<!-- tabs:start -->

Expand Down Expand Up @@ -181,7 +193,7 @@ public:
int maxPartitionsAfterOperations(string s, int k) {
int n = s.size();
unordered_map<long long, int> f;
function<int(int, int, int)> dfs = [&](int i, int cur, int t) {
auto dfs = [&](this auto&& dfs, int i, int cur, int t) -> int {
if (i >= n) {
return 1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,19 @@ tags:

<!-- solution:start -->

### Solution 1
### Solution 1: Memoized Search

We design a function $\textit{dfs}(i, \textit{cur}, t)$ that represents the maximum number of partitions we can obtain when currently processing index $i$ of string $s$, the current prefix already contains the character set $\textit{cur}$, and we can still modify $t$ characters. Then the answer is $\textit{dfs}(0, 0, 1)$.

The execution logic of function $\textit{dfs}(i, \textit{cur}, t)$ is as follows:

1. If $i \geq n$, it means we have finished processing string $s$, return 1.
2. Calculate the bitmask $v = 1 \ll (s[i] - 'a')$ corresponding to the current character $s[i]$, and calculate the updated character set $\textit{nxt} = \textit{cur} \mid v$.
3. If the number of bits in $\textit{nxt}$ exceeds $k$, it means the current prefix already contains more than $k$ distinct characters. We need to make a partition, increment the partition count by 1, and recursively call $\textit{dfs}(i + 1, v, t)$. Otherwise, continue recursively calling $\textit{dfs}(i + 1, \textit{nxt}, t)$.
4. If $t > 0$, it means we can still modify a character once. We try to change the current character $s[i]$ to any lowercase letter (26 choices in total). For each choice, calculate the updated character set $\textit{nxt} = \textit{cur} \mid (1 \ll j)$, and based on whether it exceeds $k$ distinct characters, choose the corresponding recursive call method to update the maximum partition count.
5. Use a hash table to cache already computed states to avoid redundant calculations.

The time complexity is $O(n \times |\Sigma| \times k)$ and the space complexity is $O(n \times |\Sigma| \times k)$, where $n$ is the length of string $s$, and $|\Sigma|$ is the size of the character set.

<!-- tabs:start -->

Expand Down Expand Up @@ -179,7 +191,7 @@ public:
int maxPartitionsAfterOperations(string s, int k) {
int n = s.size();
unordered_map<long long, int> f;
function<int(int, int, int)> dfs = [&](int i, int cur, int t) {
auto dfs = [&](this auto&& dfs, int i, int cur, int t) -> int {
if (i >= n) {
return 1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ class Solution {
int maxPartitionsAfterOperations(string s, int k) {
int n = s.size();
unordered_map<long long, int> f;
function<int(int, int, int)> dfs = [&](int i, int cur, int t) {
auto dfs = [&](this auto&& dfs, int i, int cur, int t) -> int {
if (i >= n) {
return 1;
}
Expand All @@ -28,4 +28,4 @@ class Solution {
};
return dfs(0, 0, 1);
}
};
};