豆包刷题:最少前缀操作问题

95 阅读4分钟

问题描述

小U和小R有两个字符串,分别是SS和TT,现在小U需要通过对SS进行若干次操作,使其变成TT的一个前缀。操作可以是修改SS的某一个字符,或者删除SS末尾的字符。现在你需要帮助小U计算出,最少需要多少次操作才能让SS变成TT的前缀。


测试样例

样例1:

输入:S = "aba", T = "abb"
输出:1

样例2:

输入:S = "abcd", T = "efg"
输出:4

样例3:

输入:S = "xyz", T = "xy"
输出:1

样例4:

输入:S = "hello", T = "helloworld"
输出:0

样例5:

输入:S = "same", T = "same"
输出:0

分析

我们需要通过两种操作将字符串 S 转换为字符串 T 的前缀:

  1. 修改操作:可以修改 S 中的某个字符,使其匹配 T 中对应位置的字符。
  2. 删除操作:可以删除 S 中的字符,直到 S 的长度和 T 的前缀相匹配。

我们的目标是最小化这些操作次数,使得 S 变成 T 的前缀。

思路

  1. 前缀匹配

    • 如果 S 的某个前缀已经是 T 的前缀,那么我们可以通过删除 S 中多余的字符来使其变成 T 的前缀,删除操作的次数是 S 的多余部分的长度。
    • 如果 S 和 T 的前缀不匹配,我们可以逐字符修改 S 中的不匹配字符,直到它们的前缀匹配为止。
  2. 最长公共前缀

    • 我们的关键是找到 S 和 T 的最长公共前缀(LCP,Longest Common Prefix)。最长公共前缀的长度 L,表示了从头开始两个字符串匹配的部分。之后的字符我们需要进行修改或删除操作。

    • 计算出最长公共前缀后,剩下的操作分为:

      • 删除操作:从 S 的末尾删除剩余部分。
      • 修改操作:将 S 中与 T 对应部分的字符修改为 T 中的字符。
  3. 最少操作

    • 删除部分:如果 S 的前缀已经匹配了 T,那么删除 S 中多余的字符。
    • 修改部分:如果 S 中的某些字符与 T 不匹配,需要通过修改来使它们匹配。

解决步骤

  1. 计算 S 和 T 的最长公共前缀的长度 L

  2. 对于剩余的部分:

    • 如果 S 长度大于 L,则需要删除 S 中的多余部分。
    • 如果 S 的长度小于 T,则需要修改 S 的部分字符,使其成为 T 的前缀。

代码实现

def solution(S: str, T: str) -> int:
    # 初始化操作次数
    operations = 0
    
    # 遍历字符串 S 和 T
    for i in range(min(len(S), len(T))):
        if S[i] != T[i]:
            operations += 1
    
    # 如果 S 的长度大于 T 的长度,需要删除多余的 S 的字符
    if len(S) > len(T):
        operations += len(S) - len(T)
    
    return operations

if __name__ == '__main__':
    print(solution("aba", "abb") == 1)
    print(solution("abcd", "efg") == 4)
    print(solution("xyz", "xy") == 1)
    print(solution("hello", "helloworld") == 0)
    print(solution("same", "same") == 0)

测试样例

样例 1

输入:S = "aba", T = "abb"

  • 公共前缀:ab(长度为 2)
  • 删除操作:len("aba") - 2 = 1
  • 修改操作:len("abb") - 2 = 1
  • 最少操作次数:1 (删除) + 1 (修改) = 2

输出:1

样例 2

输入:S = "abcd", T = "efg"

  • 公共前缀:""(长度为 0)
  • 删除操作:len("abcd") - 0 = 4
  • 修改操作:len("efg") - 0 = 3
  • 最少操作次数:4 (删除) + 3 (修改) = 7

输出:4

样例 3

输入:S = "xyz", T = "xy"

  • 公共前缀:xy(长度为 2)
  • 删除操作:len("xyz") - 2 = 1
  • 修改操作:len("xy") - 2 = 0
  • 最少操作次数:1 (删除) + 0 (修改) = 1

输出:1

样例 4

输入:S = "hello", T = "helloworld"

  • 公共前缀:hello(长度为 5)
  • 删除操作:len("hello") - 5 = 0
  • 修改操作:len("helloworld") - 5 = 5
  • 最少操作次数:0 (删除) + 0 (修改) = 0

输出:0

样例 5

输入:S = "same", T = "same"

  • 公共前缀:same(长度为 4)
  • 删除操作:len("same") - 4 = 0
  • 修改操作:len("same") - 4 = 0
  • 最少操作次数:0 (删除) + 0 (修改) = 0

输出:0

总结

这个问题的核心是找出 ST 的最长公共前缀,基于这个前缀来计算最少的操作次数。通过删除和修改,我们能够有效地将 S 转换成 T 的前缀。