编辑距离下最多 "UCC" 子串 | 豆包MarsCode AI刷题

28 阅读2分钟

一、题目解析

题目描述
给定字符串 SSS 由 'U' 和 'C' 组成,通过编辑操作(插入、删除、替换字符)在编辑距离不超过 mmm 的限制下,最大化字符串中 "UCC" 子串的数量。

编辑操作

  • 插入:在任意位置插入字符。
  • 删除:删除任意字符。
  • 替换:将任意字符替换为另一个字符。

目标
计算能够通过编辑操作生成的最多 "UCC" 子串数量。


二、解题思路

  1. 状态定义
    使用动态规划计算最大 "UCC" 子串数量。
    定义 dp[i][j]dp[i][j]dp[i][j]:前 iii 个字符在允许 jjj 次编辑操作时,可以形成的最大 "UCC" 子串数量。

  2. 状态转移

    • 当前字符直接参与: 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" 所需的编辑距离。
  3. 结果计算
    遍历字符串和编辑距离限制,动态更新最大 "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)

四、知识总结

  1. 动态规划的灵活性
    动态规划可以解决带约束的最优化问题。本题通过 dpdpdp 数组存储不同编辑距离的最优解,状态转移根据是否能生成 "UCC" 子串更新。

  2. 编辑距离计算

    • 替换:cost=1。
    • 插入/删除:根据需求调整编辑成本。
    • 本题中根据 "UCC" 的相似度计算编辑成本。
  3. 字符串匹配的扩展
    字符串匹配问题可以结合动态规划和编辑距离模型,处理更复杂的约束。