问题121 字符串趋同最小代价问题 | 豆包MarsCode AI刷题

65 阅读3分钟

问题描述

小U 和 小R 各自拥有一个长度相等的二进制字符串 A 和 B。现在,他们想要将这两个字符串修改成相同的字符串。每次修改可以选择以下两种操作:

交换同一个字符串中的任意两个字符,交换操作的成本为它们索引之差的绝对值 |i - j|。 对某个字符进行取反操作,取反的成本为 2。 小U 和 小R 想知道,将字符串 A 和 B 修改为相同字符串的最小总成本是多少?

思路

首先,考虑所有A,B不同的字符,易得在最优的答案中,每一个字符不可能被操作多余一次,并且当在i,j的字符距离大于等于四时,总是可以通过将两者取反获得不弱于置换的结果。

不妨让+1,-1分别表示A和B字符的两种可能不匹配,0表示A和B这一位匹配。

考虑字符串最后一个不同字符的处理方式,则分类讨论可以发现,当且仅当最后四位是以下情况时,将最后一位和之前的某一位置换要优于取反:

  • ? ? -1 +1
  • ? -1 0 +1
  • -1 0 0 +1
  • -1 -1 +1 +1

其余情况直接取反最后一位要由于置换。 所以不断重复以上操作,我们便可得到答案。

代码示例
int solution(const std::string& str1, const std::string& str2) {
    if(!str1.size()) {
        return 0;
    }
    string s1 = "0000"+str1;
    string s2 = "0000"+str2;
    vector<int> dp(s1.size(),0);
    for(int i=4;i<s1.size();i++) {
        dp[i] = dp[i-1] + 2;
        if(s1[i]==s2[i]) {
            dp[i] = dp[i-1];
        } else if(s1[i-1]!=s2[i-1]&&s1[i-1]!=s1[i]) {
                dp[i] = min(dp[i],dp[i-2] + 1);
        } else if(s1[i-1]==s2[i-1]&&s1[i-2]!=s2[i-2]&&s1[i-2]!=s1[i]) {
            dp[i] = min(dp[i],dp[i-3] + 2);
        } else if(s1[i-1]==s2[i-1]&&s1[i-2]==s2[i-2]&&s1[i-3]!=s2[i-3]&&s1[i-3]!=s1[i]) {
            dp[i] = min(dp[i],dp[i-4] + 3);
        }
        else if(s1[i-1]!=s2[i-1]&&s1[i-1]==s1[i]&&s1[i-2]!=s2[i-2]&&s1[i-2]!=s1[i]&&s1[i-3]!=s2[i-3]&&s1[i-3]!=s1[i]) {
            dp[i] = min(dp[i],dp[i-4] + 4);
        }
        cout << dp[i] <<" ";
    }
    return dp[s1.size()-1];  
}
代码示例

int solution(const std::string& str1, const std::string& str2) { if(!str1.size()) { return 0; } string s1 = "0000"+str1; string s2 = "0000"+str2; vector dp(s1.size(),0); for(int i=4;i<s1.size();i++) { dp[i] = dp[i-1] + 2; if(s1[i]==s2[i]) { dp[i] = dp[i-1]; } else if(s1[i-1]!=s2[i-1]&&s1[i-1]!=s1[i]) { dp[i] = min(dp[i],dp[i-2] + 1); } else if(s1[i-1]==s2[i-1]&&s1[i-2]!=s2[i-2]&&s1[i-2]!=s1[i]) { dp[i] = min(dp[i],dp[i-3] + 2); } else if(s1[i-1]==s2[i-1]&&s1[i-2]==s2[i-2]&&s1[i-3]!=s2[i-3]&&s1[i-3]!=s1[i]) { dp[i] = min(dp[i],dp[i-4] + 3); } else if(s1[i-1]!=s2[i-1]&&s1[i-1]==s1[i]&&s1[i-2]!=s2[i-2]&&s1[i-2]!=s1[i]&&s1[i-3]!=s2[i-3]&&s1[i-3]!=s1[i]) { dp[i] = min(dp[i],dp[i-4] + 4); } cout << dp[i] <<" "; } return dp[s1.size()-1];
}