最少前缀操作问题(题解)

121 阅读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

我们可以注意到要非最后一个字符只能修改,因此前面必然把S和T修改成一样的字符

我们可以遍历S字符串 默认当前遍历到的字符即为修改后的字符串的结尾

如果当前值和T字符串相同则继续遍历

如果不相同则记录当前已经修改过的次数 并考虑将后面的字符全部删除

然后与之前情况的答案取较小值

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

int solution(string S, string T) {
    int m = S.size();
    int n = T.size();
    int ans = m;
    int tmp = 0;
    for(int i = 0 ; i < m ; i++){
        if(i >= n){ //特判S比T长的情况
            break;
        }
        if(S[i] != T[i]) {
            tmp ++;
        }
        ans = min(tmp + m - i - 1, ans);
    }
    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;
}

问题描述

小U得到一个只包含小写字母的字符串 S。她可以执行如下操作:每次选择字符串中两个相同的字符删除,然后在字符串末尾添加一个任意的小写字母。小U想知道,最少需要多少次操作才能使得字符串中的所有字母都不相同?


测试样例

样例1:

输入:S = "abab"
输出:2

样例2:

输入:S = "aaaa"
输出:2

样例3:

输入:S = "abcabc"
输出:3

首先我们考虑如何将"aaaaa"转化为"a"的情况

可以注意到操作的本质是将字符的数量减少1

再考虑能转换成其他字符的最优解应该如何转化: 应该是将当前两个相同的字符转化为未出现过的字符 , 当前的字符数量就会减少2 未出现过的字符就会减少1

因此我们可以用一个桶来记录每个字符出现过了几次 然后再计算出未出现过的字符有几个

遍历一遍桶如果桶中的数量等于即只要操作一次 并且不需要占用未出现过的字符

如果大于2就需要占用未出现过的字符 如果没有未出现过的字符 那么则需要(数量-1)次操作才能将其化为独一无二的字符

#include <iostream>
#include <string>
#include <vector>
using namespace std;
int solution(const std::string& S) {
    // write code here
    vector<int> to(26);
    int num = 0;
    for(auto i : S){
        to[i - 'a']++;
        if(to[i - 'a'] == 1) num++;
    }
    int sy = 26 - num;
    int ans = 0;
    for(auto i : to){
        if(i == 2){
            ans++;
        }
        else if(i > 2){
            if(sy){
                int cost = min((i - 1)/ 2 , sy);
                ans += cost;
                if(i % 2 == 0) ans++;
                sy = sy - cost;
            }
            else ans += i - 1;
        }
    }
    return ans;
}

int main() {
    std::cout << (solution("abab") == 2) << std::endl;
    std::cout << (solution("aaaa") == 2) << std::endl;
    std::cout << (solution("abcabc") == 3) << std::endl;
}