符串修改成含特定子串 问题描述 小S手里有一个由小写字母组成的字符串。她的目标是通过修改字符串中的字母,使得字符串中至少包含 m m个uccu子串。每次修改,允许将字符串中的任意一个字母修改成其他任意小写字母。小S希望你帮她计算出为了达到目标所需的最小修改次数。如果无法通过任何方式达到目标,则输出-1。
为了计算出将字符串修改成至少包含 mmm 个 "uccu" 子串所需的最小修改次数,我们可以按照以下步骤来实现:
- 查找现有的 "uccu" 子串:首先遍历字符串,找到所有已经存在的 "uccu" 子串,并记录其数量。
- 计算所需的修改次数:如果当前存在的 "uccu" 子串数量已经大于或等于 mmm,则不需要进行任何修改。如果不足,则需要计算缺少的数量,并确定将哪些字符修改为形成新的 "uccu" 子串所需的最小修改次数。
- 虽然uccuccu只有7个字符,但是第一个uccu子串的最后一个u可以作为下一个uccu的首位u
- 构建 "uccu" 子串:可以通过滑动窗口的方式来检查可以形成 "uccu" 的子串,并计算所需的修改次数。
public class Main { public static int solution(int n, int m, String s) { // 检查字符串长度是否足够 if (n < 4 * m - (m - 1)) return -1;
// 统计已存在的 "uccu" 子串数量,允许共享字符
int existingCount = 0;
for (int i = 0; i <= n - 4; i++) {
if (s.substring(i, i + 4).equals("uccu")) {
existingCount++;
i += 3; // 跳到下一个可能的 "uccu" 开始
}
}
// 如果现有 "uccu" 子串已满足或超过要求,返回 0
if (existingCount >= m) {
return 0;
}
// 计算需要额外生成的 "uccu" 数量
int needed = m - existingCount;
int minChanges = Integer.MAX_VALUE;
// 遍历每一个长度为4的窗口,将其转换成 "uccu" 的最少修改次数
for (int i = 0; i <= n - 4 && needed > 0; i++) {
int currentChanges = 0;
String substring = s.substring(i, i + 4);
// 计算将当前子串转换为 "uccu" 所需的修改次数
if (substring.charAt(0) != 'u') currentChanges++;
if (substring.charAt(1) != 'c') currentChanges++;
if (substring.charAt(2) != 'c') currentChanges++;
if (substring.charAt(3) != 'u') currentChanges++;
// 更新最少修改次数
minChanges = Math.min(minChanges, currentChanges);
}
// 计算最终的修改次数
int changes = needed * minChanges;
// 如果仍不足以形成所需的 "uccu" 数量,返回 -1;否则返回总修改次数
return minChanges == Integer.MAX_VALUE ? -1 : changes;
}
public static void main(String[] args) {
System.out.println(solution(4, 1, "ucuc") == 2);
System.out.println(solution(7, 2, "uccuccu") == 0);
System.out.println(solution(7, 1, "abcdefg") == 3);
System.out.println(solution(17, 8, "ccuuuucuucccucuuc") == -1);
System.out.println(solution(6, 1, "tbnxwf") == 4); // 新增测试用例
}
}