|
|
|
|
package class_2022_08_4_week;
|
|
|
|
|
|
|
|
|
|
// 来自网易
|
|
|
|
|
// 小红拿到了一个仅由r、e、d组成的字符串
|
|
|
|
|
// 她定义一个字符e为"好e" : 当且仅当这个e字符和r、d相邻
|
|
|
|
|
// 例如"reeder"只有一个"好e",前两个e都不是"好e",只有第三个e是"好e"
|
|
|
|
|
// 小红每次可以将任意字符修改为任意字符,即三种字符可以相互修改
|
|
|
|
|
// 她希望"好e"的数量尽可能多
|
|
|
|
|
// 小红想知道,自己最少要修改多少次
|
|
|
|
|
// 输入一个只有r、e、d三种字符的字符串
|
|
|
|
|
// 长度 <= 2 * 10^5
|
|
|
|
|
// 输出最小修改次数
|
|
|
|
|
public class Code06_MinCostMostE {
|
|
|
|
|
|
|
|
|
|
// public static class Info {
|
|
|
|
|
// public int mostGoodE;
|
|
|
|
|
// public int minCost;
|
|
|
|
|
//
|
|
|
|
|
// public Info(int good, int cost) {
|
|
|
|
|
// mostGoodE = good;
|
|
|
|
|
// minCost = cost;
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// // i-2 -> prepre
|
|
|
|
|
// // i-1 -> pre
|
|
|
|
|
// // i...可以去成全 i-1 pre
|
|
|
|
|
// // 也可以不成全
|
|
|
|
|
// // i -> r e d 随意
|
|
|
|
|
// // 返回:i-1 yes or no + i.... 最多的好e,数量是多少
|
|
|
|
|
// // 最多的好e, 最小的代价
|
|
|
|
|
// // i 2 * 10^5
|
|
|
|
|
// // prepre r e d
|
|
|
|
|
// // pre r e d
|
|
|
|
|
// // 9 * 2 * 10^5
|
|
|
|
|
// // 10^6
|
|
|
|
|
// public static Info zuo(char[] s, int i, char prepre, char pre) {
|
|
|
|
|
// if (i == s.length) {
|
|
|
|
|
// return new Info(0, 0);
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// // 可能性1 i-1 [i] -> r
|
|
|
|
|
// int cur1Value = prepre == 'd' && pre == 'e' ? 1 : 0;
|
|
|
|
|
// int cur1Cost = s[i] == 'r' ? 0 : 1;
|
|
|
|
|
// Info info1 = zuo(s, i + 1, pre, 'r');
|
|
|
|
|
// int p1Value = cur1Value + info1.mostGoodE;
|
|
|
|
|
// int p1Cost = cur1Cost + info1.minCost;
|
|
|
|
|
//
|
|
|
|
|
// // 可能性2 i-1 [i] -> e
|
|
|
|
|
// int cur2Value = 0;
|
|
|
|
|
// int cur2Cost = s[i] == 'e' ? 0 : 1;
|
|
|
|
|
// Info info2 = zuo(s, i + 1, pre, 'e');
|
|
|
|
|
// int p2Value = cur2Value + info2.mostGoodE;
|
|
|
|
|
// int p2Cost = cur2Cost + info2.minCost;
|
|
|
|
|
//
|
|
|
|
|
// // 可能性3 i-1 [i] -> d
|
|
|
|
|
// int cur3Value = prepre == 'r' && pre == 'e' ? 1 : 0;
|
|
|
|
|
// int cur3Cost = s[i] == 'd' ? 0 : 1;
|
|
|
|
|
// Info info3 = zuo(s, i + 1, pre, 'd');
|
|
|
|
|
// int p3Value = cur3Value + info3.mostGoodE;
|
|
|
|
|
// int p3Cost = cur3Cost + info3.minCost;
|
|
|
|
|
//
|
|
|
|
|
// int mostE = 0;
|
|
|
|
|
// int minCost = Integer.MAX_VALUE;
|
|
|
|
|
//
|
|
|
|
|
// if (mostE < p1Value) {
|
|
|
|
|
// mostE = p1Value;
|
|
|
|
|
// minCost = p1Cost;
|
|
|
|
|
// } else if (mostE == p1Value) {
|
|
|
|
|
// minCost = Math.min(minCost, p1Cost);
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// if (mostE < p2Value) {
|
|
|
|
|
// mostE = p2Value;
|
|
|
|
|
// minCost = p2Cost;
|
|
|
|
|
// } else if (mostE == p2Value) {
|
|
|
|
|
// minCost = Math.min(minCost, p2Cost);
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// if (mostE < p3Value) {
|
|
|
|
|
// mostE = p3Value;
|
|
|
|
|
// minCost = p3Cost;
|
|
|
|
|
// } else if (mostE == p3Value) {
|
|
|
|
|
// minCost = Math.min(minCost, p3Cost);
|
|
|
|
|
// }
|
|
|
|
|
// return new Info(mostE, minCost);
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
public static int minCost(String str) {
|
|
|
|
|
int n = str.length();
|
|
|
|
|
if (n < 3) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
int[] arr = new int[n];
|
|
|
|
|
// d认为是0,e认为是1,r认为是2
|
|
|
|
|
for (int i = 0; i < n; i++) {
|
|
|
|
|
char cur = str.charAt(i);
|
|
|
|
|
if (cur == 'd') {
|
|
|
|
|
arr[i] = 0;
|
|
|
|
|
} else if (cur == 'e') {
|
|
|
|
|
arr[i] = 1;
|
|
|
|
|
} else {
|
|
|
|
|
arr[i] = 2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 通过上面的转化,问题变成了:
|
|
|
|
|
// 1的左右,一定要被0和2包围,这个1才是"好1"
|
|
|
|
|
// 请让"好1"的尽量多,返回最少的修改代价
|
|
|
|
|
int maxGood = 0;
|
|
|
|
|
int minCost = Integer.MAX_VALUE;
|
|
|
|
|
for (int prepre = 0; prepre < 3; prepre++) {
|
|
|
|
|
for (int pre = 0; pre < 3; pre++) {
|
|
|
|
|
int cost = arr[0] == prepre ? 0 : 1;
|
|
|
|
|
cost += arr[1] == pre ? 0 : 1;
|
|
|
|
|
Info cur = process(arr, 2, prepre, pre);
|
|
|
|
|
if (cur.maxGood > maxGood) {
|
|
|
|
|
maxGood = cur.maxGood;
|
|
|
|
|
minCost = cur.minCost + cost;
|
|
|
|
|
} else if (cur.maxGood == maxGood) {
|
|
|
|
|
minCost = Math.min(minCost, cur.minCost + cost);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return minCost;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static class Info {
|
|
|
|
|
public int maxGood;
|
|
|
|
|
public int minCost;
|
|
|
|
|
|
|
|
|
|
public Info(int a, int b) {
|
|
|
|
|
maxGood = a;
|
|
|
|
|
minCost = b;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 暴力递归
|
|
|
|
|
// 可以自己改成动态规划
|
|
|
|
|
// arr[index-2]位置的数值是prepre
|
|
|
|
|
// arr[index-1]位置的数值是pre
|
|
|
|
|
// 在这种情况下,请让arr[index...]上的好1尽量多
|
|
|
|
|
// 返回:
|
|
|
|
|
// 尽量多的"好1",是多少?
|
|
|
|
|
// 得到尽量多的"好1",最小代价是多少?
|
|
|
|
|
public static Info process(int[] arr, int index, int prepre, int pre) {
|
|
|
|
|
if (index == arr.length) {
|
|
|
|
|
return new Info(0, 0);
|
|
|
|
|
}
|
|
|
|
|
// 可能性1,arr[index],变成0
|
|
|
|
|
int p1Value = prepre == 2 && pre == 1 ? 1 : 0;
|
|
|
|
|
int p1Cost = arr[index] == 0 ? 0 : 1;
|
|
|
|
|
Info info = process(arr, index + 1, pre, 0);
|
|
|
|
|
p1Value += info.maxGood;
|
|
|
|
|
p1Cost += info.minCost;
|
|
|
|
|
// 可能性2,arr[index],变成1
|
|
|
|
|
int p2Value = 0;
|
|
|
|
|
int p2Cost = arr[index] == 1 ? 0 : 1;
|
|
|
|
|
info = process(arr, index + 1, pre, 1);
|
|
|
|
|
p2Value += info.maxGood;
|
|
|
|
|
p2Cost += info.minCost;
|
|
|
|
|
// 可能性3,arr[index],变成2
|
|
|
|
|
int p3Value = prepre == 0 && pre == 1 ? 1 : 0;
|
|
|
|
|
int p3Cost = arr[index] == 2 ? 0 : 1;
|
|
|
|
|
info = process(arr, index + 1, pre, 2);
|
|
|
|
|
p3Value += info.maxGood;
|
|
|
|
|
p3Cost += info.minCost;
|
|
|
|
|
// 开始决策,选出三种可能性中的最优解
|
|
|
|
|
int maxGood = 0;
|
|
|
|
|
int minCost = Integer.MAX_VALUE;
|
|
|
|
|
if (p1Value > maxGood) {
|
|
|
|
|
maxGood = p1Value;
|
|
|
|
|
minCost = p1Cost;
|
|
|
|
|
} else if (p1Value == maxGood) {
|
|
|
|
|
minCost = Math.min(minCost, p1Cost);
|
|
|
|
|
}
|
|
|
|
|
if (p2Value > maxGood) {
|
|
|
|
|
maxGood = p2Value;
|
|
|
|
|
minCost = p2Cost;
|
|
|
|
|
} else if (p2Value == maxGood) {
|
|
|
|
|
minCost = Math.min(minCost, p2Cost);
|
|
|
|
|
}
|
|
|
|
|
if (p3Value > maxGood) {
|
|
|
|
|
maxGood = p3Value;
|
|
|
|
|
minCost = p3Cost;
|
|
|
|
|
} else if (p3Value == maxGood) {
|
|
|
|
|
minCost = Math.min(minCost, p3Cost);
|
|
|
|
|
}
|
|
|
|
|
return new Info(maxGood, minCost);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|