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

117 阅读2分钟
题目:

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

题目分析

题目一共给出两个字符串分别是S,T,对字符串S中的字符进行修改或者删除末尾的字符,让字符串S变成字符串T的前缀,要求操作次数最小。首先由于对S的操作只有修改或者删除末尾字符,所以前面的字符修改不用担心字符串长度改变的问题。先求S,T的长度,求出两个字符串中最短的长度。遍历这两个字符串该长度的字符,相同的不用改变,操作数不变,不同的需要操作数加一。遍历完成后,让字符串S的长度减去字符串T的长度,如果字符串S的长度比字符串T的长度长,需要将这些字符删除,操作数加上S多出的长度。代码如下:

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

int solution(string S, string T) {
    int len1=S.length();
    int len2=T.length();
    int sum=0;
    int len=len1>=len2?len2:len1;
    for(int i=0;i<len;i++){
        if(S[i]!=T[i]){
            sum++;
        }
    }
    int dif=len1-len2;
    if(dif>0){
        sum+=dif;
    }
    return sum;
}

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

以上是我自己在做的想法。其实按照动态规划还可以这样分析。先建一个二维数组dp[i][j],i表示S前i个字符,j表示T的前j个字符。当i=0时,没有任何的操作可言,所以dp[0][j]=0;当j=0时,i可以通过删除i次来变成T的前缀,所以dp[i][j]=i;S[i-1] == T[j-1],则不需要修改,可以直接继承前一个状态的操作次数,即dp[i][j] = dp[i-1][j-1]。如果S[i-1] != T[j-1],则有两种选择:修改S[i-1]为T[j-1],此时操作次数为dp[i-1][j-1] + 1。删除S[i-1]此时操作次数为dp[i-1][j] + 1。其实修改和删除的操作数的一样,并且对最后的结果都没有影响。就像aba改成abb的前缀一样,无论你是将a改成b,还是将a删除你都可以得到abb的前缀而且操作数都一样。所以我觉得没有什么影响。