package class10; // 本题测试链接 : https://leetcode-cn.com/problems/boolean-evaluation-lcci/ public class Code05_BooleanEvaluation { public static int countEval0(String express, int desired) { if (express == null || express.equals("")) { return 0; } char[] exp = express.toCharArray(); int N = exp.length; Info[][] dp = new Info[N][N]; Info allInfo = func(exp, 0, exp.length - 1, dp); return desired == 1 ? allInfo.t : allInfo.f; } public static class Info { public int t; public int f; public Info(int tr, int fa) { t = tr; f = fa; } } // 限制: // L...R上,一定有奇数个字符 // L位置的字符和R位置的字符,非0即1,不能是逻辑符号! // 返回str[L...R]这一段,为true的方法数,和false的方法数 public static Info func(char[] str, int L, int R, Info[][] dp) { if (dp[L][R] != null) { return dp[L][R]; } int t = 0; int f = 0; if (L == R) { t = str[L] == '1' ? 1 : 0; f = str[L] == '0' ? 1 : 0; } else { // L..R >=3 // 每一个种逻辑符号,split枚举的东西 // 都去试试最后结合 for (int split = L + 1; split < R; split += 2) { Info leftInfo = func(str, L, split - 1, dp); Info rightInfo = func(str, split + 1, R, dp); int a = leftInfo.t; int b = leftInfo.f; int c = rightInfo.t; int d = rightInfo.f; switch (str[split]) { case '&': t += a * c; f += b * c + b * d + a * d; break; case '|': t += a * c + a * d + b * c; f += b * d; break; case '^': t += a * d + b * c; f += a * c + b * d; break; } } } dp[L][R] = new Info(t, f); return dp[L][R]; } public static int countEval1(String express, int desired) { if (express == null || express.equals("")) { return 0; } char[] exp = express.toCharArray(); return f(exp, desired, 0, exp.length - 1); } public static int f(char[] str, int desired, int L, int R) { if (L == R) { if (str[L] == '1') { return desired; } else { return desired ^ 1; } } int res = 0; if (desired == 1) { for (int i = L + 1; i < R; i += 2) { switch (str[i]) { case '&': res += f(str, 1, L, i - 1) * f(str, 1, i + 1, R); break; case '|': res += f(str, 1, L, i - 1) * f(str, 0, i + 1, R); res += f(str, 0, L, i - 1) * f(str, 1, i + 1, R); res += f(str, 1, L, i - 1) * f(str, 1, i + 1, R); break; case '^': res += f(str, 1, L, i - 1) * f(str, 0, i + 1, R); res += f(str, 0, L, i - 1) * f(str, 1, i + 1, R); break; } } } else { for (int i = L + 1; i < R; i += 2) { switch (str[i]) { case '&': res += f(str, 0, L, i - 1) * f(str, 1, i + 1, R); res += f(str, 1, L, i - 1) * f(str, 0, i + 1, R); res += f(str, 0, L, i - 1) * f(str, 0, i + 1, R); break; case '|': res += f(str, 0, L, i - 1) * f(str, 0, i + 1, R); break; case '^': res += f(str, 1, L, i - 1) * f(str, 1, i + 1, R); res += f(str, 0, L, i - 1) * f(str, 0, i + 1, R); break; } } } return res; } public static int countEval2(String express, int desired) { if (express == null || express.equals("")) { return 0; } char[] exp = express.toCharArray(); int N = exp.length; int[][][] dp = new int[2][N][N]; dp[0][0][0] = exp[0] == '0' ? 1 : 0; dp[1][0][0] = dp[0][0][0] ^ 1; for (int i = 2; i < exp.length; i += 2) { dp[0][i][i] = exp[i] == '1' ? 0 : 1; dp[1][i][i] = exp[i] == '0' ? 0 : 1; for (int j = i - 2; j >= 0; j -= 2) { for (int k = j; k < i; k += 2) { if (exp[k + 1] == '&') { dp[1][j][i] += dp[1][j][k] * dp[1][k + 2][i]; dp[0][j][i] += (dp[0][j][k] + dp[1][j][k]) * dp[0][k + 2][i] + dp[0][j][k] * dp[1][k + 2][i]; } else if (exp[k + 1] == '|') { dp[1][j][i] += (dp[0][j][k] + dp[1][j][k]) * dp[1][k + 2][i] + dp[1][j][k] * dp[0][k + 2][i]; dp[0][j][i] += dp[0][j][k] * dp[0][k + 2][i]; } else { dp[1][j][i] += dp[0][j][k] * dp[1][k + 2][i] + dp[1][j][k] * dp[0][k + 2][i]; dp[0][j][i] += dp[0][j][k] * dp[0][k + 2][i] + dp[1][j][k] * dp[1][k + 2][i]; } } } } return dp[desired][0][N - 1]; } }