047 表达式得到期望结果的组合种数
Table of Contents

ac

给定一个只由0(假)、1(真)、&(逻辑与)、|(逻辑或)和^(异或)五种字符组成的字符串express,再给定一个布尔值desires。求出express能有多少种组合方式,可以达到desired的结果。并输出你所求出的总方案数对10^9+7取模后的值。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;


class Record{
    long trueCnt;
    long falseCnt;

    public Record() {
        this.trueCnt = 0;
        this.falseCnt = 0;
    }

    public Record(long trueCnt, long falseCnt) {
        this.trueCnt = trueCnt;
        this.falseCnt = falseCnt;
    }
}

public class Main {

    public static Scanner sc = new Scanner(System.in);

    static int M = (int)Math.pow(10, 9) + 7;

    public static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));


    public static void main(String[] args) throws Exception{
        String express = reader.readLine();
        String desired = reader.readLine();
        char[] exp = express.toCharArray();
        boolean b = desired.equals("false") ? false : true;
        System.out.println(process(exp, b));
    }

    static boolean isValid(char[] exp){
        int n = exp.length;
        if((n & 1) == 0){ // 偶数 false
            return false;
        }
        // 偶数位置必须是0,1
        for(int i=0;i<n;i+=2){
            if(!(exp[i] == '0' || exp[i] == '1')){
                return false;
            }
        }
        // 奇数位置必须是运算符号
        for(int i=1;i<n;i+=2){
            if(!(exp[i] == '&' || exp[i] == '|' || exp[i] == '^')){
                return false;
            }
        }
        return true;
    }

    static int getTrueOrFalse(char operator, int left, int right){
        int tmp = 0;
        if(operator == '&'){
            tmp = left & right;
        }
        if(operator == '|'){
            tmp = left | right;
        }
        if(operator == '^'){
            tmp = left ^ right;
        }
        return tmp;
    }

    static boolean val2bool(int val){
       return val == 1 ? true : false;
    }

    static int bool2val(boolean b){
        return b ? 1 : 0;
    }

    // 时间复杂度O(n^3)
    // 空间复杂度O(n^2)
    static long process(char[] exp, boolean desired){
        if(exp == null || exp.length == 0){
            return 0;
        }
        if(!isValid(exp)){
            return 0;
        }
        int n = exp.length;
        // 只有奇数位置才有
        Record[][] dp = new Record[n][n];
        // 长度为1的
        for(int i=0;i<n;i+=2){
            Record record = new Record();
            if(exp[i] == '1'){
                record.trueCnt = 1;
            }else {
                record.falseCnt = 1;
            }
            dp[i][i] = record;
        }
        // 长度为3,5,7...
        for(int len=3;len<=n;len+=2){
            // 求 dp[l...r]
            for(int i=0;i<n;i+=2){
                int l = i;
                int r = i + len - 1;
                if(r >= n){
                    continue;
                }
                // 求 exp[i...r] 的情况
                long trueCnt = 0;
                long falseCnt = 0;
                for(int j=l;j<r;j+=2){
                    // 分成两部分[l...j],[j+2...r] 中间符号
                    char operator = exp[j+1];
                    if(dp[l][j].trueCnt > 0 && dp[j+2][r].trueCnt > 0){
                        int tmpVal = getTrueOrFalse(operator, 1, 1);
                        if(val2bool(tmpVal)){
                            trueCnt += dp[l][j].trueCnt * dp[j+2][r].trueCnt % M;
                        }else {
                            falseCnt += dp[l][j].trueCnt * dp[j+2][r].trueCnt % M;
                        }
                    }
                    if(dp[l][j].trueCnt > 0 && dp[j+2][r].falseCnt > 0){
                        int tmpVal = getTrueOrFalse(operator, 1, 0);
                        if(val2bool(tmpVal)){
                            trueCnt += dp[l][j].trueCnt * dp[j+2][r].falseCnt % M;
                        }else {
                            falseCnt += dp[l][j].trueCnt * dp[j+2][r].falseCnt % M;
                        }
                    }
                    if(dp[l][j].falseCnt > 0 && dp[j+2][r].trueCnt > 0){
                        int tmpVal = getTrueOrFalse(operator, 0, 1);
                        if(val2bool(tmpVal)){
                            trueCnt += dp[l][j].falseCnt * dp[j+2][r].trueCnt % M;
                        }else {
                            falseCnt += dp[l][j].falseCnt * dp[j+2][r].trueCnt % M;
                        }
                    }
                    if(dp[l][j].falseCnt > 0 && dp[j+2][r].falseCnt > 0){
                        int tmpVal = getTrueOrFalse(operator, 0, 0);
                        if(val2bool(tmpVal)){
                            trueCnt += dp[l][j].falseCnt * dp[j+2][r].falseCnt % M;
                        }else {
                            falseCnt += dp[l][j].falseCnt * dp[j+2][r].falseCnt % M;
                        }
                    }
                    trueCnt %= M;
                    falseCnt %= M;
                }
                dp[l][r] = new Record(trueCnt % M,falseCnt % M);
            }
        }
        long ans = desired ? dp[0][n-1].trueCnt : dp[0][n-1].falseCnt;
        return ans % M;
    }

}
/*
1^0|0|1
false

2
1^((0|0)|1)和1^(0|(0|1))可以得到false

1
false

0

1^1&1|1|0&1|1|1|0&1&0^0|1^0&0^0^0&0&1|1&1|1^0&1^0|0|1^0&1|0^0&1^1&1^1^1^1^0^1^1&1&1&1|1|0|1^1|0|1&0&1^0|0&1&1&0|0|1&0&0|1&1|1|1&0|0&0&0^0^1&1^0&0^0^0^1&1^0^1&0|0&1&1&1&0^1|1^0|1^0|0|0^1|1&0|0^0|1&1&0^1|1&0^0&0^0|1^0&1^0&1&1^0|1|0&1&1&1&1|0^1^0^0&1|1|1&0|1|0|1^0&0&1|1^1&1&1^0&1^0^0&1&0^1^0|1|1|0^0|0&0^1|1|0^0|1^1&0^1^1^1&0&1^1&0&1&0^0|1|1^0|0^1|0^0|1&0|0|0|0&1^0&0|0^0&1&0^0^0&0|0^0^1|1&0&1|0^1&1|0|1|0^1^1&1&1^1^0|1^0&1^0^0^0^0&1|0|0^1^0^1^1|0&0^1|1|1^0&0^0|1^1|1^1|1^1^0^0|1|0^1&1^1^1|1&0&1^0^0^0
true

320147386
 */