12最大UCC子串计算-掘金刷题

问题描述

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

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

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

约束条件:

  • 字符串长度不超过1000

测试样例

样例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" 子串。

代码:

public class Main {
    public static int solution(int m, String s) {
        int n = s.length();
        boolean[] used = new boolean[n];
        int cnt = 0;
        int ans = 0;

        // 找到现有的UCC子串
        for (int i = 2; i < n; i++) {
            if (s.substring(i - 2, i + 1).equals("UCC")) {
                used[i] = used[i - 1] = used[i - 2] = true;
                cnt += 3;
                ans++;
            }
        }

        // 找到未使用的UC子串或者CC子串
        for (int i = 1; i < n; i++) {
            if (!used[i] && !used[i - 1] && m > 0) {
                String t = s.substring(i - 1, i + 1);
                if (t.equals("UC") || t.equals("CC")) {
                    used[i] = used[i - 1] = true;
                    cnt += 2;
                    ans++;
                    m--;
                }
            }
        }

        // 处理剩下的单个字符
        ans += Math.min(m / 2, n - cnt);
        m -= Math.min(m / 2, n - cnt) * 2;

        // 如果还有编辑次数大于2,将其分成3个字符一组,相当加入一组UCC字符串
        if (m > 2) {
            ans += m / 3;
        }
        //返回结果
        return ans;
    }

    public static void main(String[] args) {
        System.out.println(solution(3, "UCUUCCCCC") == 3);
        System.out.println(solution(6, "U") == 2);
        System.out.println(solution(2, "UCCUUU") == 2);
    }
}

代码解释:

类和方法定义

public class Main {
    public static int solution(int m, String s) {
        // 函数体
    }

    public static void main(String[] args) {
        // 函数体
    }
}

  • public class Main:定义了一个名为 Main 的公共类。
  • public static int solution(int m, String s):定义了一个名为 solution 的静态方法,它接收一个整数 m 和一个字符串 s 作为参数,并返回一个整数结果。
  • public static void main(String[] args):定义了程序的主方法,用于程序的入口点。

solution 方法内部实现

int n = s.length();
boolean[] used = new boolean[n];
int cnt = 0;
int ans = 0;

  • int n = s.length();:获取输入字符串 s 的长度并存储在变量 n 中。
  • boolean[] used = new boolean[n];:创建一个长度为 n 的布尔型数组 used,用于标记字符串 s 中字符是否已被使用。
  • int cnt = 0;:用于统计已使用的字符数量。
  • int ans = 0;:存储最终的结果,即满足条件的子串数量。

找到现有的 UCC 子串

for (int i = 2; i < n; i++) {
    if (s.substring(i - 2, i + 1).equals("UCC")) {
        used[i] = used[i - 1] = used[i - 2] = true;
        cnt += 3;
        ans++;
    }
}

  • 这是一个 for 循环,从索引 2 开始遍历字符串 s 直到索引 n - 1
  • s.substring(i - 2, i + 1).equals("UCC"):使用 substring 方法提取从 i - 2 到 i 的子串(不包括 i + 1),并检查是否等于 "UCC"
  • 如果等于 "UCC",将 used 数组中相应位置的元素标记为 true,表示这三个字符已被使用,同时将 cnt 加 3 并将 ans 加 1。

找到未使用的 UC 或 CC 子串

for (int i = 1; i < n; i++) {
    if (!used[i] &&!used[i - 1] && m > 0) {
        String t = s.substring(i - 1, i + 1);
        if (t.equals("UC") || t.equals("CC")) {
            used[i] = used[i - 1] = true;
            cnt += 2;
            ans++;
            m--;
        }
    }
}

  • 另一个 for 循环,从索引 1 开始遍历字符串 s 直到索引 n - 1
  • if (!used[i] &&!used[i - 1] && m > 0):检查当前字符和前一个字符是否未被使用,并且 m(编辑次数)大于 0。
  • String t = s.substring(i - 1, i + 1);:提取从 i - 1 到 i 的子串(不包括 i + 1)。
  • 如果子串等于 "UC" 或 "CC",将相应位置的元素标记为 true,将 cnt 加 2,ans 加 1,并将 m 减 1。

处理剩下的单个字符

ans += Math.min(m / 2, n - cnt);
m -= Math.min(m / 2, n - cnt) * 2;

  • ans += Math.min(m / 2, n - cnt);:将 ans 增加 m / 2 和 n - cnt 中的较小值,即将剩下的编辑次数尽可能平均分配给未使用的字符,每次处理两个字符。
  • m -= Math.min(m / 2, n - cnt) * 2;:更新 m 的值,减去已经使用的编辑次数。

如果还有编辑次数大于 2,将其分成 3 个字符一组

if (m > 2) {
    ans += m / 3;
}

  • 如果 m 大于 2,将 m 除以 3 并将结果累加到 ans 中,相当于添加 UCC 字符串组。

main 方法内部实现

System.out.println(solution(3, "UCUUCCCCC") == 3);
System.out.println(solution(6, "U") == 2);
System.out.println(solution(2, "UCCUUU") == 2);

  • 调用 solution 方法并传入不同的参数,打印方法的返回结果是否等于给定的值,用于测试 solution 方法的功能。

这段代码的主要目的是对输入的字符串 s 进行处理,根据给定的编辑次数 m ,找出并计算出满足特定条件(如 "UCC""UC""CC")的子串的最大数量。首先查找已有的 "UCC" 子串,然后使用剩余的编辑次数查找 "UC" 或 "CC" 子串,最后将剩余的编辑次数尽可能地用于生成新的子串。同时,使用 used 数组来标记字符是否已被使用,避免重复使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值