12. 最大UCC子串计算 解析 | 豆包MarsCode AI刷题

32 阅读4分钟

题目大意

给定一个由字符 'U' 和 'C' 组成的字符串 SS,在不超过 mm插入、删除或替换单个字符的条件下,使字符串中 "UCC" 子串的数量最多。

测试样例及解释

样例1:

输入:m = 3,s = "UCUUCCCCC"
输出:3

可以将字符串修改为 "UCCUCCUCC"(2 次替换操作,不超过给定值 m = 3),包含 3 个 "UCC" 子串。

样例2:

输入:m = 6,s = "U"
输出:2

可以将字符串修改为 "UCCUCC",(5 次插入操作,不超过给定值 m = 6),包含 2 个 "UCC" 子串。

样例3:

输入:m = 2,s = "UCCUUU"
输出:2

可以将字符串修改为 "UCCUCC",(2 次替换操作,不超过给定值 m = 2),包含 2 个 "UCC" 子串。

解题思路

  1. 我们可以发现,删除、替换操作一定不会比插入操作更优秀:

这一点的核心在于尽可能保留更多的字符以备后续组合;由于目标子串长度仅为 3,这种贪心策略是可行的,不需要动态规划就可以完成。

举例来说,如果存在形如 “UCUC” 的字符串,我们可以通过一次删除操作获得 “UCC” ,或是通过一次替换操作获得 “UCCC”,但我们也可以通过一次插入操作获得 “UCCUC” ,在同样包含一个目标子串的同时保留了一个 "UC" ,如果还有一次操作机会就可以变为 “UCCUCC”,再次得到一个目标子串,而如果进行了删除操作或是替换操作则无法达成。

  1. 在确认只进行插入操作后,我们就需要通过尽可能少的操作使 SS 内的所有字符均为某个 "UCC" 的一部分,这一点也是可以通过贪心得到的,核心思想是尽可能少的破坏原有字符串,具体情况如下:
int ans=0,s1=0,s2=0;//分别记录答案数量,当前长度为1的子串数量,当前长度为2的子串数量
int i=0;
while(i<s.size()){//遍历整个字符串 S
    if(s[i]=='U'){//如果当前以'U'开头
        if(i+1>=s.size()||s[i+1]=='U'){//后续无字符或紧跟着一个'U',无法延伸
            s1++;//记录长度为1的子串数量
            i++;//当前子串为"U"结束,寻找下一个子串
        }//此时需要两次插入操作获得一个目标子串"UCC"
        else if(i+2>=s.size()||s[i+2]=='U'){//紧跟着一个'C',但后续无字符或紧跟着一个'U',无法延伸
            s2++;//记录长度为2的子串数量
            i+=2;//当前子串为"UC"结束,寻找下一个子串
        }//此时需要一次插入操作获得一个目标子串"UCC"
        else{//当前子串已经为"UCC"
            ans++;//目标子串数量+1
            i+=3;//当前子串为"UCC"结束,寻找下一个子串
        }
    }
    else{//如果当前以'C'开头
        if(i+1>=s.size()||s[i+1]=='U'){//后续无字符或紧跟着一个'U',无法延伸
            s1++;//记录长度为1的子串数量
            i++;//当前子串为"C"结束,寻找下一个子串
        }//此时需要两次插入操作获得一个目标子串"UCC"
        else{//紧跟着一个'C',可在开头插入一个'U'组成"UCC"
            s2++;//记录长度为2的子串数量
            i+=2;//当前子串为"CC"结束,寻找下一个子串
        }//此时需要一次插入操作获得一个目标子串"UCC"
    }
}
  1. 获得了当前长度为1、2的子串数量后,我们的策略便是优先补齐当前长度为2的子串,因为每一次操作都可以获得一个新的目标子串;在补齐所有当前长度为2的子串后再去补齐当前长度为1的子串,每两次次操作可以获得一个新的目标子串;如果在补齐所有当前长度为1的子串后还有次数剩余,我们就可以每三次获得一个新的目标子串,得到最终答案:
ans+=std::min(m,s2);//优先补齐当前长度为2的子串
m-=std::min(m,s2);//计算剩余操作次数
ans+=std::min(m/2,s1);//补齐当前长度为1的子串
m-=std::min(m/2,s1)*2;//计算剩余操作次数
ans+=m/3;//添加全新的目标子串
  1. 最后将 ansans 返回即可。