最大UCC子串计算 MarsCode-AI刷题

212 阅读3分钟

问题描述

小S有一个由字符 'U' 和 'C' 组成的字符串 SS,并希望在编辑距离不超过给定值 mm 的条件下,尽可能多地在字符串中找到 "UCC" 子串。

编辑距离定义为将字符串 SS 转化为其他字符串时所需的最少编辑操作次数。允许的每次编辑操作是插入、删除或替换单个字符。你需要计算在给定的编辑距离限制 mm 下,能够包含最多 "UCC" 子串的字符串可能包含多少个这样的子串。

例如,对于字符串"UCUUCCCCC"和编辑距离限制m = 3,可以通过编辑字符串生成最多包含3个"UCC"子串的序列。


测试样例

样例1:

输入:m = 3,s = "UCUUCCCCC"
输出:3

样例2:

输入:m = 6,s = "U"
输出:2

样例3:

输入:m = 2,s = "UCCUUU"
输出:2

解释

样例1:可以将字符串修改为 "UCCUCCUCC"(2 次替换操作,不超过给定值 m = 3),包含 3 个 "UCC" 子串。

样例2:后面插入 5 个字符 "CCUCC"(5 次插入操作,不超过给定值 m = 6),可以将字符串修改为 "UCCUCC",包含 2 个 "UCC" 子串。

样例3:替换最后 2 个字符,可以将字符串修改为 "UCCUCC",包含 2 个 "UCC" 子串。

问题理解

我们需要在一个由 'U' 和 'C' 组成的字符串 S 中,通过不超过 m 次编辑操作(插入、删除、替换),尽可能多地生成 "UCC" 子串。

数据结构选择

由于我们需要频繁地检查和修改字符串,并且需要计算编辑距离,因此可以考虑使用动态规划(DP)来解决这个问题。

算法步骤

  1. 定义状态

    • 我们可以使用一个二维数组 dp[i][j],其中 i 表示当前字符串的长度,j 表示当前的编辑距离。dp[i][j] 表示在当前字符串长度为 i,编辑距离为 j 的情况下,最多能包含多少个 "UCC" 子串。
  2. 状态转移

    • 对于每个字符 S[i],我们可以选择保留它、删除它、或者替换它。
    • 如果保留 S[i],则 dp[i][j] = dp[i-1][j]
    • 如果删除 S[i],则 dp[i][j] = dp[i-1][j-1]
    • 如果替换 S[i],则 dp[i][j] = dp[i-1][j-1]
    • 如果插入一个字符,则 dp[i][j] = dp[i][j-1]
  3. 边界条件

    • 当 i = 0 时,dp[0][j] = 0,因为空字符串不能包含任何 "UCC" 子串。
    • 当 j = 0 时,dp[i][0] 表示不进行任何编辑操作,直接计算原始字符串中 "UCC" 的个数。
  4. 计算 "UCC" 子串

    • 在每次状态转移时,检查当前字符串是否可以形成新的 "UCC" 子串,并更新 dp 数组。

总结

通过动态规划,我们可以有效地计算在给定编辑距离限制下,最多能包含多少个 "UCC" 子串。希望这些思路能帮助你更好地理解问题并开始编写代码。

    n = len(s)
    # 初始化 dp 数组
    dp = [[0] * (m + 1) for _ in range(n + 1)]
    
    # 初始化边界条件
    for j in range(m + 1):
        dp[0][j] = 0  # 空字符串不能包含任何 "UCC" 子串
    
    # 状态转移
    for i in range(1, n + 1):
        for j in range(m + 1):
            # 保留当前字符
            dp[i][j] = dp[i-1][j]
            
            # 删除当前字符
            if j > 0:
                dp[i][j] = max(dp[i][j], dp[i-1][j-1])
            
            # 替换当前字符
            if j > 0:
                dp[i][j] = max(dp[i][j], dp[i-1][j-1])
            
            # 插入字符
            if j > 0:
                dp[i][j] = max(dp[i][j], dp[i][j-1])
            
            # 检查是否可以形成新的 "UCC" 子串
            if i >= 3 and s[i-3:i] == "UCC":
                dp[i][j] += 1
    
    # 返回结果
    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)