![]() |
VOOZH | about |
Given a boolean expression s that contain symbols and operators. The task is to count the number of ways we can parenthesize the expression so that the value of the expression evaluates to true.
Symbols
Operators
Examples:
Input: s = T|T&F^T
Output: 4
Explanation: The expression evaluates to true in 4 ways ((T|T)&(F^T)), (T|(T&(F^T))), (((T|T)&F)^T) and (T|((T&F)^T)).Input: s = T^F|F
Output: 2
Explanation: ((T^F)|F) and (T^(F|F)) are the only ways.
Important Point:
When calculating ways to make an expression evaluate to true, we also need to consider combinations where subexpressions evaluate to false because operators like XOR can produce true when one operand is false. For example, if we have "F^T", even though the left subexpression evaluates to false, the XOR operation with true on the right gives us true as the final result. Therefore, we need to keep track of both true and false counts for subexpressions to handle all possible combinations correctly.
Table of Content
The idea is to solve this recursively by splitting the expression at each operator and evaluating all possible combinations of true/false values from the left and right subexpressions. For each operator position k, we parenthesize the expression into two parts: (i, k-1) and (k+1, j). We then recursively calculate how many ways each part can evaluate to true and false. Once we have these counts, we can combine them based on the operator at position k.
4
If we notice carefully, we can observe that the above recursive solution holds the following two properties of Dynamic Programming:
1. Optimal Substructure: Number of ways to make expression s[i, j] evaluate to req depends on the optimal solutions of countWays(i, k-1, 0), countWays(i, k-1, 1), countWays(k+1, j, 0) and countWays(k+1, j, 1) where k lies between i and j.
2. Overlapping Subproblems: While applying a recursive approach in this problem, we notice that certain subproblems are computed multiple times. For example, countWays(0, 4, 1) and countWays(0, 7, 1) will call the same subproblem countWays(0, 2, 0) twice.
4
This problem is solved using tabulation (bottom-up DP). We define a 3D DP table where:
dp[i][j][1]stores the number of ways the subexpressions[i:j]evaluates to True.dp[i][j][0]stores the number of ways the subexpressions[i:j]evaluates to False.To fill the DP table, we iterate over all possible substrings
s[i:j]and break them into two parts at every operators[k]. The left part iss[i:k-1], and the right part iss[k+1:j]. Based on the operator (&,|,^), we compute the number of ways to getTrueandFalse.The final result is stored in
dp[0][n-1][1], which gives the total ways to evaluate the full expression toTrue.
Illustration:
The iterative implementation is going to be tricky here we initially know diagonal values (which are 0), our result is going to be at the top right corner (or dp[0][n-1][1]) and we never access lower diagonal values. So we cannot fill the matrix with a normal traversal, we rather need to fill in diagonal manner. We fill the matrix using a variable len that stores differences between row and column indexes. We keep increasing len by 2 until it becomes n-1 (for the top right element)
4