一、题目解析
题目描述
给定字符串 SSS 由 'U' 和 'C' 组成,通过编辑操作(插入、删除、替换字符)在编辑距离不超过 mmm 的限制下,最大化字符串中 "UCC" 子串的数量。
编辑操作
- 插入:在任意位置插入字符。
- 删除:删除任意字符。
- 替换:将任意字符替换为另一个字符。
目标
计算能够通过编辑操作生成的最多 "UCC" 子串数量。
二、解题思路
-
状态定义
使用动态规划计算最大 "UCC" 子串数量。
定义 dp[i][j]dp[i][j]dp[i][j]:前 iii 个字符在允许 jjj 次编辑操作时,可以形成的最大 "UCC" 子串数量。 -
状态转移
- 当前字符直接参与: dp[i][j]=dp[i−1][j]dp[i][j] = dp[i-1][j]dp[i][j]=dp[i−1][j],无需编辑操作。
- 当前字符通过编辑操作构成 "UCC": 如果满足编辑距离限制,则: dp[i][j]=max(dp[i][j],dp[i−3][j−edit_cost]+1)dp[i][j] = \max(dp[i][j], dp[i - 3][j - \text{edit_cost}] + 1)dp[i][j]=max(dp[i][j],dp[i−3][j−edit_cost]+1) 其中 edit_cost\text{edit_cost}edit_cost 是将当前字符转换为 "UCC" 所需的编辑距离。
-
结果计算
遍历字符串和编辑距离限制,动态更新最大 "UCC" 子串数量。
三、代码实现
以下是基于上述思路的代码实现:
python
复制代码
def solution(m: int, s: str) -> int:
n = len(s)
target = "UCC"
t_len = len(target)
# 定义 dp 表,dp[i][j] 表示前 i 个字符允许 j 次编辑时最大 "UCC" 数量
dp = [[0] * (m + 1) for _ in range(n + 1)]
# 遍历字符串和编辑距离
for i in range(1, n + 1):
for j in range(m + 1):
# 当前字符不使用时
dp[i][j] = dp[i - 1][j]
# 检查是否能构成 "UCC"
if i >= t_len:
# 计算构成 "UCC" 的最小编辑距离
edit_cost = sum(s[i - t_len + k] != target[k] for k in range(t_len))
# 如果编辑距离在范围内,尝试构成一个 "UCC"
if j >= edit_cost:
dp[i][j] = max(dp[i][j], dp[i - t_len][j - edit_cost] + 1)
# 返回使用所有字符且允许 m 次编辑时的最大 "UCC" 数量
return dp[n][m]
# 测试用例
if __name__ == '__main__':
print(solution(m=3, s="UCUUCCCCC") == 3)
print(solution(m=6, s="U") == 2)
print(solution(m=2, s="UCCUUU") == 2)
四、知识总结
-
动态规划的灵活性
动态规划可以解决带约束的最优化问题。本题通过 dpdpdp 数组存储不同编辑距离的最优解,状态转移根据是否能生成 "UCC" 子串更新。 -
编辑距离计算
- 替换:cost=1。
- 插入/删除:根据需求调整编辑成本。
- 本题中根据 "UCC" 的相似度计算编辑成本。
-
字符串匹配的扩展
字符串匹配问题可以结合动态规划和编辑距离模型,处理更复杂的约束。