最少前缀操作问题 | 豆包MarsCode AI刷题

105 阅读3分钟

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

测试样例

样例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

题目链接:www.marscode.cn/practice/8e…

分析

我们需要将字符串 S 转换为字符串 T 的前缀,操作可以是修改 S 中的字符或删除 S 末尾的字符。目标是计算最少操作次数。因为只能删除末尾的字符,所以就不需要用dp了,直接遍历找到不一样的字符替换即可,长度不一样的即代表进行末尾删除操作。

代码逻辑

  1. 逻辑判断

    • 如果 T 的长度 m 大于或等于 S 的长度 n,则只需要考虑修改操作。
    • 如果 T 的长度 m 小于 S 的长度 n,则需要考虑修改操作和删除操作。
  2. 修改操作

    • 在 m >= n 的情况下,遍历 S 和 T 的相同长度的部分,计算不同字符的数量,并累加到 res 中。
    • 在 m < n 的情况下,同样计算不同字符的数量,并累加到 res 中。
  3. 删除操作

    • 在 m < n 的情况下,还需要删除 S 中多余的 n - m 个字符,因此将 n - m 累加到 res 中。

证明

1. 修改操作的正确性

  • 当 m >= n 时,S 和 T 的前 n 个字符需要进行比较。如果 S[i] != T[i],则需要一次修改操作。
  • 当 m < n 时,S 和 T 的前 m 个字符需要进行比较。如果 S[i] != T[i],则需要一次修改操作。

2. 删除操作的正确性

  • 当 m < n 时,S 比 T 长,需要删除 S 中多余的 n - m 个字符,使其长度与 T 相同。

具体证明

情况1:m >= n

  • 在这种情况下,S 和 T 的前 n 个字符需要进行比较。
  • 如果 S[i] != T[i],则需要一次修改操作。
  • 因此,res 累加的是 S 和 T 前 n 个字符中不同字符的数量。

情况2:m < n

  • 在这种情况下,S 和 T 的前 m 个字符需要进行比较。
  • 如果 S[i] != T[i],则需要一次修改操作。
  • 此外,S 比 T 长,需要删除 S 中多余的 n - m 个字符。
  • 因此,res 累加的是 S 和 T 前 m 个字符中不同字符的数量,再加上 n - m 次删除操作。

代码如下:

#include <iostream>
#include <string>
using namespace std;

int solution(string S, string T) {
    // write code here
    int n = S.size(), m = T.size();
    int res = 0;
    if (m >= n) {
        for (int i = 0; i < n; i++) {
            res += S[i] != T[i];
        }
        return res;
    }
    for (int i = 0; i < m; i++) res += S[i] != T[i];
    res += n - m;
    return res;
}

int main() {
    cout << (solution("aba", "abb") == 1) << endl;
    cout << (solution("abcd", "efg") == 4) << endl;
    cout << (solution("xyz", "xy") == 1) << endl;
    cout << (solution("hello", "helloworld") == 0) << endl;
    cout << (solution("same", "same") == 0) << endl;
    return 0;
}

image.png