最少前缀和操作问题| MarsCode

80 阅读5分钟

问题描述

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

问题分析

我们需要通过对字符串 S 进行若干次操作,使其变成字符串 T 的一个前缀。操作可以是修改 S 的某一个字符,或者删除 S 末尾的字符。目标是计算出最少需要多少次操作。

解题思路

  1. 比较字符串长度:首先,比较 S 和 T 的长度。如果 S 的长度大于 T 的长度,那么 S 需要删除一些字符,直到长度与 T 相同。

  2. 逐字符比较:从字符串的开头逐字符比较 S 和 T。如果字符相同,继续比较下一个字符;如果字符不同,则需要进行修改操作。

  3. 计算操作次数:统计需要修改的字符数和需要删除的字符数。

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

int solution(string S, string T) {
    // write code here
    int ct = 0;
    int mn = S.size() < T.size()? S.size() : T.size();
    int mx = S.size() > T.size()? S.size() : T.size();
    for(int i = 0 ; i < mn;i++)
        if(S[i]==T[i])ct++;


    return  S.size() - ct;
  
}

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

我们来看看ai的思路,个人感觉不想太行,用的模拟方法,代码繁杂;

MarsCode AI

好的,让我们来分析一下这个问题。

问题理解

我们需要通过对字符串 S 进行若干次操作,使其变成字符串 T 的一个前缀。操作可以是修改 S 的某一个字符,或者删除 S 末尾的字符。目标是计算出最少需要多少次操作。

解题思路

  1. 前缀匹配:首先,我们需要找到 S 和 T 的最长公共前缀。这个前缀部分不需要任何操作。

  2. 操作计算

    • 对于 S 中不在最长公共前缀中的字符,我们需要进行修改或删除操作。
    • 对于 T 中不在最长公共前缀中的字符,S 需要进行删除操作。

算法步骤

  1. 初始化操作次数为0

  2. 双指针遍历:使用两个指针分别遍历 S 和 T,直到其中一个指针到达字符串末尾。

    • 如果 S[i] == T[j],则两个指针都向后移动。

    • 如果 S[i] != T[j],则需要进行操作:

      • 如果 S 的指针 i 可以向后移动(即 S 还有字符),则删除 S[i],操作次数加1。
      • 如果 S 的指针 i 不能向后移动(即 S 已经遍历完),则需要修改 S[i] 使其等于 T[j],操作次数加1。
  3. 剩余字符处理:如果 S 的指针已经到达末尾,但 T 的指针还没有到达末尾,则需要删除 S 的剩余部分,操作次数加剩余字符数。

伪代码


-   []()
-   []()
-   []()

int solution(string S, string T) {

    int i = 0, j = 0;

    int operations = 0;

    

    while (i < S.size() && j < T.size()) {

        if (S[i] == T[j]) {

            // 字符匹配,继续比较下一个字符

            i++;

            j++;

        } else {

            // 字符不匹配,需要进行操作

            if (i < S.size() - 1) {

                // 删除 S[i]

                operations++;

                i++;

            } else {

                // 修改 S[i] 使其等于 T[j]

                operations++;

                i++;

                j++;

            }

        }

    }

    

    // 如果 S 还有剩余字符,需要删除

    if (i < S.size()) {

        operations += S.size() - i;

    }

    

    // 如果 T 还有剩余字符,S 需要删除这些字符

    if (j < T.size()) {

        operations += T.size() - j;

    }

    

    return operations;

}

### 代码框架

你可以根据上述思路,在 `solution` 函数中实现具体的代码逻辑。

```cpp

-   []()
-   []()
-   []()

int solution(string S, string T) {

    int i = 0, j = 0;

    int operations = 0;

    

    // 双指针遍历 S 和 T

    while (i < S.size() && j < T.size()) {

        if (S[i] == T[j]) {

            // 字符匹配,继续比较下一个字符

            i++;

            j++;

        } else {

            // 字符不匹配,需要进行操作

            if (i < S.size() - 1) {

                // 删除 S[i]

                operations++;

                i++;

            } else {

                // 修改 S[i] 使其等于 T[j]

                operations++;

                i++;

                j++;

            }

        }

    }

    

    // 如果 S 还有剩余字符,需要删除

    if (i < S.size()) {

        operations += S.size() - i;

    }

    

    // 如果 T 还有剩余字符,S 需要删除这些字符

    if (j < T.size()) {

        operations += T.size() - j;

    }

    

    return operations;

}

你找一下规律,再用代码实现,不要模拟

MarsCode AI

好的,我们可以通过找规律来简化问题。让我们分析一下问题的本质:

规律分析

  1. 最长公共前缀:首先,我们需要找到 S 和 T 的最长公共前缀。这个前缀部分不需要任何操作。

  2. 剩余部分的处理

    • 对于 S 中不在最长公共前缀中的字符,我们需要进行修改或删除操作。
    • 对于 T 中不在最长公共前缀中的字符,S 需要进行删除操作。

简化思路

  1. 计算最长公共前缀的长度:使用双指针法,找到 S 和 T 的最长公共前缀的长度 prefix_len

  2. 计算操作次数

    • S 中不在最长公共前缀中的字符数为 S.size() - prefix_len
    • T 中不在最长公共前缀中的字符数为 T.size() - prefix_len
    • 总操作次数为 S.size() - prefix_len + T.size() - prefix_len

代码实现

根据上述规律,我们可以直接计算出最少操作次数。




#include <iostream>

#include <string>

using namespace std;

int solution(string S, string T) {

    int prefix_len = 0;

    

    // 计算最长公共前缀的长度

    while (prefix_len < S.size() && prefix_len < T.size() && 

    S[prefix_len] == T[prefix_len]) {

        prefix_len++;

    }

    

    // 计算操作次数

    int operations = (S.size() - prefix_len) + (T.size() - 

    prefix_len);

    

    return operations;

}

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;

}```

### 解释

1.  **计算最长公共前缀的长度**:使用 `while` 循环找到 `S` 和 `T` 的最长公共前缀的长度 `prefix_len`。
1.  **计算操作次数**:根据 `prefix_len`,计算 `S` 和 `T` 中不在最长公共前缀中的字符数,并求和得到总操作次数。

希望这个简化后的代码实现能帮助你更好地理解问题并实现代码。如果有任何问题,欢迎继续提问!
欧克阿,感觉还可以,思路简单多了。