最大UCC字串计算 | 豆包MarsCode AI刷题

218 阅读4分钟

问题描述

小S有一个由字符 'U' 和 'C' 组成的字符串 SS,并希望在编辑距离不超过给定值 mm 的条件下,尽可能多地在字符串中找到 "UCC" 子串。

编辑距离定义为将字符串 SS 转化为其他字符串时所需的最少编辑操作次数。允许的每次编辑操作是插入、删除或替换单个字符。你需要计算在给定的编辑距离限制 mm 下,能够包含最多 "UCC" 子串的字符串可能包含多少个这样的子串。

例如,对于字符串"UCUUCCCCC"和编辑距离限制m = 3,可以通过编辑字符串生成最多包含3个"UCC"子串的序列。


测试样例

样例1:

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

样例2:

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

样例3:

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

解释

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

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

样例3:替换最后 2 个字符,可以将字符串修改为 "UCCUCC",包含 2 个 "UCC" 子串。


问题拆解与分析

  1. 编辑距离定义

    • 我们允许的编辑操作包括:

      • 插入:在字符串的任意位置插入一个字符。
      • 删除:删除字符串中的任意一个字符。
      • 替换:将字符串中的某个字符替换为另一个字符。
    • 每次操作的成本为 1,总操作次数不能超过给定的编辑距离 m

    • 通过思考可以发现,由于我们需要构造UCC子串,而输入串只包含U和C字符,所以理论上输入字串的所有字符都是有用字符。字符排序不符合UCC顺序时候,要实现最小距离达到最大的字串数量,则只需要考虑插入操作。


解题思路

为了解决此问题,我们采用以下步骤:

  1. 统计现有 "UCC" 子串数量
    通过将所有完整匹配的 "UCC" 子串标记,我们得到当前字符串中直接匹配的 "UCC" 数量n

  2. 优化局部模式

    • 插入单个字母获得字串:(如 "UC" 或 "CC")为 "UCC"。
    • 每次操作距离 m -1。
    • 每次操作"UCC" 数量 n +1。
  3. 全局优化

    • 若还存在剩余字符,则只可能为U和C的单个字符,每个字符添加两个字符即可组成"UCC"。
    • 每次操作距离 m -2。
    • 每次操作"UCC" 数量 n +1。
  4. 终止条件
    以上每次操作中,若编辑预算耗尽(m <= 0)时,输出当前最大化的 "UCC" 子串数量。

    • 如果经过上述操作后m仍然>0,则直接插入整个"UCC"字串
    • 每次操作距离 m -3。
    • 每次操作"UCC" 数量 n +1。

代码实现与解释

以下代码实现基于上述解题思路,利用字符串替换、统计和贪心优化解决问题:

import java.util.ArrayList;

public class Main {

    // 辅助方法:统计字符串中子串 s1 的出现次数
    public static int countStr(String s, String s1) {
        return (s.length() - s.replace(s1, "").length()) / s1.length();
    }

    // 主方法:根据编辑距离限制 m 和输入字符串 s 计算最大 "UCC" 数量
    public static int solution(int m, String s) {
        // 替换所有完整的 "UCC" 子串为占位符 "AAA",统计数量
        String s1 = s.replaceAll("UCC", "AAA");
        int count = countStr(s1, "AAA");

        // 替换部分匹配模式 "UC" 或 "CC" 为占位符 "BBB",统计数量
        String s2 = s1.replace("UC", "BBB").replace("CC", "BBB");
        int count2 = countStr(s2, "BBB");
        m -= count2; // 更新编辑距离预算
        count += count2;

        // 若编辑预算耗尽,返回结果
        if (m <= 0)
            return count + m;

        // 统计剩余字符 "U" 和 "C" 的数量,用于进一步构造 "UCC"
        int count3 = countStr(s2, "U") + countStr(s2, "C");
        m -= count3 * 2; // 替换成本为 2
        count += count3;

        // 若编辑预算耗尽,返回结果
        if (m <= 0)
            return count + (m - 1) / 2;

        // 使用剩余预算通过插入操作构造更多的 "UCC"
        return count + m / 3;
    }

    public static void main(String[] args) {
        // 测试样例
        System.out.println(solution(10, "CUUUCC") == 5); // 示例 1
        System.out.println(solution(6, "U") == 2);       // 示例 2
        System.out.println(solution(2, "UCCUUU") == 2);  // 示例 3
    }
}

复杂度分析

  • 时间复杂度:字符串替换和统计操作的复杂度为 O(n),整体复杂度线性。
  • 空间复杂度:额外的字符串存储占用 O(n) 空间。

结论

本文通过字符串匹配、替换和贪心优化等手段,解决了编辑距离限制下最大化 "UCC" 子串的问题。代码在理论分析与实际测试中表现良好,具有良好的通用性和效率。