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

129 阅读3分钟

题意简述

小U和小R拥有两个字符串,分别为 S 和 T。小U的任务是通过对字符串 S 进行一系列操作,使得 S 最终成为 T 的一个前缀。允许的操作包括:

  1. 修改 S 中的任意字符。
  2. 删除 S 末尾的字符。

我们的目标是计算出将 S 转变为 T 的前缀所需的最少操作次数。

思路分析

长度比较

  • 当 |S| > |T|

    • 如果字符串 S 的长度大于字符串 T,那么必须首先通过删除 S 尾部的字符来匹配 T 的长度。具体来说,需要删除 |S| - |T| 个字符。
    • 例如,若 S = "abcde"T = "abc",则需要删除最后两个字符 d 和 e,使得 S 的长度减小到与 T 相同。
  • 当 |S| ≤ |T|

    • 若字符串 S 的长度小于或等于 T,则我们需要将 S 的字符逐个与 T 的对应字符进行比较。
    • 在这个过程中,统计 S 中与 T 对应位置字符不同的数量,即可得到需要修改的字符数量。这种情况下的最优操作策略是只进行必要的修改。

具体操作

  • 删除操作:对于 |S| > |T| 的情况,我们需要进行 |S| - |T| 次删除操作来调整 S 的长度。

  • 修改操作:若 |S| ≤ |T|,则遍历 S 中的字符与 T 进行比较。对于每一个不同的字符,增加一项修改操作的计数。具体步骤如下:

    1. 遍历 S (从0到|S| - 1)与 T(从0到|S| - 1)进行字符的比对。
    2. 计算 S[i] 和 T[i] 是否相同,若不同则计数器加1。

最终操作数计算

  • 综合两种情况,最终的操作次数可以表示为:

    • 如果 |S| > |T|操作次数=(ST)+需要修改的字符数\text{操作次数} = (|S| - |T|) + \text{需要修改的字符数}
    • 如果 |S| \leq |T|操作次数=需要修改的字符数\text{操作次数} = \text{需要修改的字符数}

示例分析

考虑以下例子:

  1. 输入:S = "abcdef"T = "abc"

    • 由于 |S| > |T|,需要删除后3个字符 def,因此需进行3次删除操作。此时 S 变为 "abc",无需修改。
    • 总操作数:3。
  2. 输入:S = "abcd"T = "abcde"

    • 由于 |S| < |T|,需要修改的字符数为0(因为长度不足,不存在可以修改的字符),可以视为 S 的后续字符可直接加。无性质修改操作。
    • 此时,只需附加一个字符 e,但是并不在操作计算中。
    • 总操作数:1(可以理解为追加而非修改)。

通过上述分析,可以很好地得出所需的操作步数。这种思路清晰地揭示了如何通过删除和修改两种基本操作,逐步将 S 变为 T 的前缀,体现了问题的合理性与步骤的有效性。

代码实现

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

int solution(string S, string T) {
    // write code here
    int ls, lt;
    ls = S.size();
    lt = T.size();
    int ans = max(0, ls - lt);
    for (int i = min(ls, lt) - 1; i >= 0; i--) {
        ans += S[i] != T[i];
    }
    return ans;
}

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;
}