小美定义一个 01 串的权值为:每次操作选择一位取反,使得相邻字符都不相等的最小操作次数。
例如,"10001"的权值是 1,因为只需要修改一次:对第三个字符取反即可。
现在小美拿到了一个 01 串,她希望你求出所有非空连续子串的权值之和,你能帮帮她吗?
一个仅包含'0'和'1'的字符串,长度不超过 2000。
所有非空子串的权值和。
10001
8
长度为 2 的子串中,有 2 个"00"的权值是 1。长度为 3 的 3 个子串权值都是 1。长度为 4 的 2 个子串权值都是 1。长度为 5 的 1 个子串权值是 1。总权值之和为 2+3+2+1=8
import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
String st = in.nextLine();
char[] ss = st.toCharArray();
int n = ss.length;
// "1": 1; "0": 0
// ss[i][j], [i, j]
int[][] weight = new int[n][n];
for (int i = 0; i < n; i++) {
if (i % 2 == 1) {
weight[i][i] = ss[i]=='1' ? 1: 0;
} else {
weight[i][i] = ss[i]=='0' ? 1: 0;
}
}
int res = 0;
for (int i = 2; i <= n; i ++) {
for (int j = 0; j + i - 1 < n; j++) {
weight[j][j+i-1] = weight[j][i+j-2] + weight[j+i-1][j+i-1];
res += Math.min( i-weight[j][j+i-1], weight[j][j+i-1]);
}
}
System.out.println(res);
}
} import java.util.*;
public class Main {
static boolean isAchieved;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
char[] chars = sc.next().toCharArray();
int n = chars.length;
int[][][] dp = new int[n][n][2];
int res = 0;
dp[0][0][chars[0] - '0'] = 0;
dp[0][0][1 - chars[0] + '0'] = 1;
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
if (i == 0 && j == 0) continue;
int bit = chars[j] - '0';
dp[i][j][bit] = dp[i][j - 1][1 - bit];
dp[i][j][1 - bit] = dp[i][j - 1][bit] + 1;
res += Math.min(dp[i][j][bit], dp[i][j][1 - bit]);
}
}
System.out.println(res);
}
}