最大UCC字串问题解析 | 豆包MarsCode AI刷题

54 阅读3分钟

题目分析

我需要在给定的字符串中,通过编辑距离不超过m次操作,尽可能多地找到 "UCC" 子串。编辑操作可以是插入、删除或者替换字符,每个操作的代价为1。我的目标是求出在这些操作限制下,能够生成多少个 "UCC" 子串。为了处理这个问题,可以使用动态规划方法,逐步构建解决方案。

解题步骤

1.初始化与定义状态

首先,定义 dp[i][e] 来表示在处理前i个字符时,编辑操作不超过e次时能够找到的 "UCC" 子串的最大数目。这里的i是字符串中已处理字符的索引,e是编辑距离的限制。

   dp[0][0] = 0 # 表示从空字符串开始,编辑距离为0时,"UCC" 子串的数目为0。

2.存储每个位置匹配 "UCC" 子串的情况

这里需要判断从每个位置i开始,如何匹配到一个 "UCC" 子串。为了做到这一点,这里定义一个match_info[i],它存储了从位置i开始,匹配到 "UCC" 子串所需的编辑操作次数和所能匹配的字符长度。

   dp_match[p][q] # 表示我们在匹配 "UCC" 子串的第 `p` 个字符时,从位置 `i` 开始匹配了 `q` 个字符的最小编辑操作次数。

通过这种方式,在每个位置i上找到所有可能的匹配方式,包括需要多少编辑操作,以及该匹配需要多少个字符。

3.更新 dp 数组

有了match_info[i]后,就可以更新dp数组。对于每个位置i,可以选择不匹配 "UCC" 子串,或者尝试通过编辑操作将字符串改成 "UCC" 子串,从而增加 "UCC" 子串的个数。

   dp[i+1][e] # 表示不匹配当前字符时,编辑操作不增加,继续处理下一个字符。
   dp[i+l][e+c] # 表示匹配到一个 "UCC" 子串后,更新 `dp`,增加一个 "UCC" 子串,并累积相应的编辑操作。

4.返回结果

最终,dp[n][e] 中的最大值即为在编辑距离不超过m的条件下,能够获得的最大 "UCC" 子串数。

完整代码

def solution(m: int, s: str) -> int:
    n = len(s)
    dp = [[-1] * (m + 1) for _ in range(n + 1)]
    dp[0][0] = 0
    match_info = [[] for _ in range(n)]
    
    for i in range(n):
        max_len = min(n - i, 3 + m)
        dp_match = [[float('inf')] * (max_len + 1) for _ in range(4)]
        dp_match[0][0] = 0
        for p in range(4):
            for q in range(max_len + 1):
                if dp_match[p][q] > m:
                    continue
                if p < 3 and q < max_len:
                    cost = 0 if s[i + q] == 'UCC'[p] else 1
                    dp_match[p + 1][q + 1] = min(dp_match[p + 1][q + 1], dp_match[p][q] + cost)
                if p < 3:
                    dp_match[p + 1][q] = min(dp_match[p + 1][q], dp_match[p][q] + 1)
                if q < max_len:
                    dp_match[p][q + 1] = min(dp_match[p][q + 1], dp_match[p][q] + 1)
        for q in range(max_len + 1):
            c = dp_match[3][q]
            match_info[i].append((c, q))
    for i in range(n + 1):
        for e in range(m + 1):
            if dp[i][e] == -1:
                continue
            if i < n:
                dp[i + 1][e] = max(dp[i + 1][e], dp[i][e])
                if e + 1 <= m:
                    dp[i + 1][e + 1] = max(dp[i + 1][e + 1], dp[i][e])
            if i < n and match_info[i]:
                for c, l in match_info[i]:
                    if e + c <= m and i + l <= n:
                        dp[i + l][e + c] = max(dp[i + l][e + c], dp[i][e] + 1)

    max_substrings = 0
    for e in range(m + 1):
        max_substrings = max(max_substrings, dp[n][e])
    
    return max_substrings

总结

按照动态规划的套路,可以能够高效地计算出在给定编辑距离限制下获得的最大 "UCC" 子串数。核心代码是建立dp数组和match_info来记录每个位置的状态,逐步推导出最终结果。