You are given a boolean expression consisting of a string of the symbols 'true', 'false', 'and', 'or', and 'xor'. Count the number of ways to parenthesize the expression such that it will evaluate to true. For example, there are 2 ways to parenthesize 'true and false xor true' such that it evaluates to true.
Given a boolean expression with following symbols.
Symbols 'T' ---> true 'F' ---> false
And following operators filled between symbols
Operators & ---> boolean AND | ---> boolean OR ^ ---> boolean XOR
Count the number of ways we can parenthesize the expression so that the value of expression evaluates to true.
Examples:
Input: symbol[] = {T, F, T} operator[] = {^, &} Output: 2 The given expression is "T ^ F & T", it evaluates true in two ways "((T ^ F) & T)" and "(T ^ (F & T))" Input: symbol[] = {T, F, F} operator[] = {^, |} Output: 2 The given expression is "T ^ F | F", it evaluates true in two ways "( (T ^ F) | F )" and "( T ^ (F | F) )". Input: symbol[] = {T, T, F, T} operator[] = {|, &, ^} Output: 4 The given expression is "T | T & F ^ T", it evaluates true in 4 ways ((T|T)&(F^T)), (T|(T&(F^T))), (((T|T)&F)^T) and (T|((T&F)^T)).
Solution:
Let T(i, j) represents the number of ways to parenthesize the symbols between i and j (both inclusive) such that the subexpression between i and j evaluates to true.
Let F(i, j) represents the number of ways to parenthesize the symbols between i and j (both inclusive) such that the subexpression between i and j evaluates to false.
Base Cases:
T(i, i) = 1 if symbol[i] = 'T' T(i, i) = 0 if symbol[i] = 'F' F(i, i) = 1 if symbol[i] = 'F' F(i, i) = 0 if symbol[i] = 'T'
The cost is :
checking subwords of size 1 + checking subwords of size 2 + ... + checking subwords of size N
= N + N-1 + 2*(N-2) + 2*(N-2) + .. + (N-1)*(1)
= O(N^3)
Auxiliary Space: O(n2)
public int countBoolParenth(char[] symbols, char[] operators) { int n = symbols.length; int[][] T = new int[n][n]; int[][] F = new int[n][n]; for (int i = 0; i < n; i++) { T[i][i] = symbols[i] == 'T' ? 1 : 0; F[i][i] = symbols[i] == 'F' ? 1 : 0; } for (int w = 2; w <= n; w++) { // w: the width of the sliding window, [2, n] for (int i = 0, j = w-1; j < n; i++, j++) { // i..j: the sliding window, [i, j] for (int k = i; k < j; k++) { // k: the index of operator to be inserted into symbols // Store Total[i][k] and Total[k+1][j] int tik = T[i][k] + F[i][k]; int tkj = T[k + 1][j] + F[k + 1][j]; // Follow the recursive formulas according to the current operator if (operators[k] == '&') { T[i][j] += T[i][k] * T[k + 1][j]; F[i][j] += (tik * tkj - T[i][k] * T[k + 1][j]); } if (operators[k] == '|') { F[i][j] += F[i][k] * F[k + 1][j]; T[i][j] += (tik * tkj - F[i][k] * F[k + 1][j]); } if (operators[k] == '^') { T[i][j] += F[i][k] * T[k + 1][j] + T[i][k] * F[k + 1][j]; F[i][j] += T[i][k] * T[k + 1][j] + F[i][k] * F[k + 1][j]; } } } } return T[0][n - 1]; }
References:
http://www.geeksforgeeks.org/dynamic-programming-set-37-boolean-parenthesization-problem/
http://people.cs.clemson.edu/~bcdean/dp_practice/dp_9.swf
http://ineptprogrammer.blogspot.com/2014/11/counting-boolean-parenthesizations-you.html
http://courses.csail.mit.edu/6.006/fall10/handouts/dpproblems-sol.pdf