Rearrange given binary strings to maximize their Bitwise XOR value - GeeksforGeeks

15 Jun, 2021
Given three binary strings S1, S2, and S3 each of length N, the task is to find the maximum possible Bitwise XOR that can be obtained by rearranging the characters of the given strings.
Examples:
Input: S1 = “1001”, S2 = “0010”, S3 = “1110”Output: 15Explanation:Rearrange the digits of S1 as “1010”, S2 as “1000” and S3 as “1101”.The XOR of these strings is “1111” which is 15 in decimal form.
Input: S1 = “11111”, S2 = “11111”, S3 = “11111” Output: 31Explanation:There is no other way to arrange the digits. Hence, XOR is “11111” which is 31 in decimal form. 
Naive Approach: The simplest approach is to generate all possible ways to rearrange S1, S2, and S3. Suppose there are O1, O2 and O3 set bits in the strings S1, S2, and S3 respectively. The total number of rearrangements to check to get the maximum Bitwise XOR value is as follows:
Total ways to rearrange S1 = NCO1  Total ways to rearrange S2 = NCO2  Total ways to rearrange S3 = NCO3  
Hence, total possible rearrangements to check = NCO1*NCO2 * NCO3
Time Complexity: O((N!)3), where N is the length of the given strings.Auxiliary Space: O(N)
Efficient Approach: The idea is to find a suitable rearrangement of S1, S2, and S3 such that their Bitwise XOR value is maximized using Dynamic Programming. The subproblems can be stored in a dp[][][][] table where dp[i][o1][o2][o3] stores the maximum XOR value up to position N-1 starting from the index i, where o1 is, o2 and o3 are the number of 1s still remaining to be placed in strings S1, S2 and S3 respectively.
There can be four cases possible at any position i from 0 to (N – 1):
Assign 1s to all the three stringsAssign 1s to any two stringsAssign 1s to any one of the strings.Assign 0s to all the strings.
Assign 1s to all the three strings
Assign 1s to any two strings
Assign 1s to any one of the strings.
Assign 0s to all the strings.
From the above possible cases for each position, calculate the maximum Bitwise XOR obtainable from the four possibilities:
Follow the steps below to solve the problem:
Initialize a table dp[][][][] to store the number of ones in S1, S2 and S3 for the positions i from 0 to N-1.
The transition states is as follows:
dp[i][o1][o2][o3] = max(dp(assign 1s to all three strings), dp(assign 1s to any of the two strings), dp(assign 1s to any one string), dp(do not assign 1 to any string)) where,
i = current positiono1 = remaining ones to be placed in the string S1o2 = remaining ones to be placed in the string S2o3 = remaining ones to be placed in the string S3
Solve the subproblems for all cases using the above transition and print the maximum XOR value amongst them.
Below is the implementation of the above approach:
C++
Java
Python3
C#
Javascript
// C++ program for the above approach #include <bits/stdc++.h>using namespace std; // Dp table to store the sub-problemsint dp[20][20][20][20]; // Function to find the maximum XOR// value after rearranging the digitsint maxXorValue(int i, string& s1,                string& s2, string& s3,                int ones1, int ones2,                int ones3, int n){    // Base Case    if (i >= n)        return 0;     // Return if already calculated    if (dp[i][ones1][ones2][ones3] != -1)        return dp[i][ones1][ones2][ones3];     int option1 = 0, option2 = 0,        option3 = 0, option4 = 0,        option5 = 0, option6 = 0,        option7 = 0, option8 = 0;     // Assigning 1's to all string at    // position 'i'.    if (ones1 > 0 && ones2 > 0        && ones3 > 0)         // 2^(n-1-i) is the value        // added to the total        option1            = (1 << ((n - 1) - i))              + maxXorValue(i + 1, s1,                            s2, s3, ones1 - 1,                            ones2 - 1,                            ones3 - 1, n);     // Assigning 1's to strings 1 & 2    if (ones1 > 0 && ones2 > 0        && (n - i > ones3))        option2            = 0              + maxXorValue(i + 1, s1,                            s2, s3, ones1 - 1,                            ones2 - 1,                            ones3, n);     // Assigning 1's to strings 2 & 3    if (ones2 > 0 && ones3 > 0        && (n - i > ones1))        option3 = 0                  + maxXorValue(i + 1, s1,                                s2, s3,                                ones1,                                ones2 - 1,                                ones3 - 1, n);     // Assigning 1's to strings 3 & 1    if (ones3 > 0 && ones1 > 0        && (n - i > ones2))        option4            = 0              + maxXorValue(i + 1, s1,                            s2, s3,                            ones1 - 1,                            ones2,                            ones3 - 1, n);     // Assigning 1 to string 1    if (ones1 > 0 && (n - i > ones2)        && (n - i > ones3))        option5 = (1 << ((n - 1) - i))                  + maxXorValue(i + 1, s1,                                s2, s3,                                ones1 - 1,                                ones2,                                ones3, n);     // Assigning 1 to string 2    if (ones2 > 0 && (n - i > ones3)        && (n - i > ones1))        option6 = (1 << ((n - 1) - i))                  + maxXorValue(i + 1, s1,                                s2, s3, ones1,                                ones2 - 1,                                ones3, n);     // Assigning 1 to string 3.    if (ones3 > 0 && (n - i > ones2)        && (n - i > ones1))        option7 = (1 << ((n - 1) - i))                  + maxXorValue(i + 1, s1,                                s2, s3, ones1,                                ones2,                                ones3 - 1, n);     // Assigning 0 to all the strings    if ((n - i > ones2) && (n - i > ones3)        && (n - i > ones1))        option8 = 0                  + maxXorValue(i + 1, s1,                                s2, s3,                                ones1,                                ones2,                                ones3, n);     // Take the maximum amongst all of    // the above solutions    return dp[i][ones1][ones2][ones3]           = max(option1,                 max(option2,                     max(option3,                         max(option4,                             max(option5,                                 max(option6,                                     max(option7,                                         option8)))))));} // Function to get the count of ones// in the string sint onesCount(string& s){    int count = 0;     // Traverse the string    for (auto x : s) {        if (x == '1')            ++count;    }     // Return the count    return count;} // Utility Function to find the maximum// XOR value after rearranging the digitsvoid maxXORUtil(string s1, string s2,                string s3, int n){     // Find the count of ones in    // each of the strings    int ones1 = onesCount(s1);    int ones2 = onesCount(s2);    int ones3 = onesCount(s3);     // Initialize dp table with -1    memset(dp, -1, sizeof dp);     // Function Call    cout << maxXorValue(0, s1, s2, s3,                        ones1, ones2,                        ones3, n);} // Driver codeint main(){    string s1 = "11110";    string s2 = "10101";    string s3 = "00111";     int n = s1.size();     // Function Call    maxXORUtil(s1, s2, s3, n);     return 0;}
// Java program for the above approachimport java.util.*;import java.lang.*;class GFG{ // Dp table to store the sub-problemsstatic int[][][][]  dp = new int[20][20][20][20];   // Function to find the maximum XOR// value after rearranging the digitsstatic int maxXorValue(int i, String s1,                       String s2, String s3,                       int ones1, int ones2,                       int ones3, int n){         // Base Case    if (i >= n)        return 0;       // Return if already calculated    if (dp[i][ones1][ones2][ones3] != -1)        return dp[i][ones1][ones2][ones3];       int option1 = 0, option2 = 0,        option3 = 0, option4 = 0,        option5 = 0, option6 = 0,        option7 = 0, option8 = 0;       // Assigning 1's to all string at    // position 'i'.    if (ones1 > 0 && ones2 > 0 &&        ones3 > 0)           // 2^(n-1-i) is the value        // added to the total        option1 = (1 << ((n - 1) - i)) +              maxXorValue(i + 1, s1, s2,                          s3, ones1 - 1,                              ones2 - 1,                              ones3 - 1, n);       // Assigning 1's to strings 1 & 2    if (ones1 > 0 && ones2 > 0 &&       (n - i > ones3))        option2 = 0 + maxXorValue(i + 1, s1, s2,                                  s3, ones1 - 1,                                      ones2 - 1,                                      ones3, n);       // Assigning 1's to strings 2 & 3    if (ones2 > 0 && ones3 > 0 &&       (n - i > ones1))        option3 = 0 + maxXorValue(i + 1, s1, s2,                                  s3, ones1,                                  ones2 - 1,                                  ones3 - 1, n);       // Assigning 1's to strings 3 & 1    if (ones3 > 0 && ones1 > 0 &&       (n - i > ones2))        option4 = 0 + maxXorValue(i + 1, s1, s2,                                  s3, ones1 - 1,                                  ones2,                                  ones3 - 1, n);       // Assigning 1 to string 1    if (ones1 > 0 && (n - i > ones2) &&       (n - i > ones3))        option5 = (1 << ((n - 1) - i)) +                  maxXorValue(i + 1, s1, s2,                              s3, ones1 - 1,                              ones2, ones3, n);       // Assigning 1 to string 2    if (ones2 > 0 && (n - i > ones3) &&       (n - i > ones1))        option6 = (1 << ((n - 1) - i)) +                  maxXorValue(i + 1, s1,                              s2, s3, ones1,                              ones2 - 1,                              ones3, n);       // Assigning 1 to string 3.    if (ones3 > 0 && (n - i > ones2) &&       (n - i > ones1))        option7 = (1 << ((n - 1) - i)) +                  maxXorValue(i + 1, s1,                              s2, s3, ones1,                              ones2,                              ones3 - 1, n);       // Assigning 0 to all the strings    if ((n - i > ones2) && (n - i > ones3) &&        (n - i > ones1))        option8 = 0 + maxXorValue(i + 1, s1,                                  s2, s3, ones1,                                  ones2, ones3, n);       // Take the maximum amongst all of    // the above solutions    return dp[i][ones1][ones2][ones3] =        Math.max(option1,                 Math.max(option2,                     Math.max(option3,                        Math.max(option4,                             Math.max(option5,                                 Math.max(option6,                                     Math.max(option7,                                              option8)))))));}   // Function to get the count of ones// in the string sstatic int onesCount(String s){    int count = 0;       // Traverse the string    for(char x : s.toCharArray())    {        if (x == '1')            ++count;    }       // Return the count    return count;}   // Utility Function to find the maximum// XOR value after rearranging the digitsstatic void maxXORUtil(String s1, String s2,                       String s3, int n){       // Find the count of ones in    // each of the strings    int ones1 = onesCount(s1);    int ones2 = onesCount(s2);    int ones3 = onesCount(s3);       // Initialize dp table with -1    for(int[][][] i : dp)        for(int[][] j : i)            for(int[] k : j)                Arrays.fill(k, -1);             // Function Call    System.out.println(maxXorValue(0, s1, s2, s3,                                   ones1, ones2,                                   ones3, n));} // Driver codepublic static void main (String[] args){    String s1 = "11110";    String s2 = "10101";    String s3 = "00111";         int n = s1.length();         // Function call    maxXORUtil(s1, s2, s3, n);}} // This code is contributed by offbeat
# Python3 program for the# above approach # Dp table to store the# sub-problemsdp = [[[[-1 for x in range(20)]            for y in range(20)]            for z in range(20)]            for p in range(20)] # Function to find the maximum# XOR value after rearranging# the digitsdef maxXorValue(i, s1, s2, s3,                ones1, ones2,                ones3, n):     # Base Case    if (i >= n):        return 0     # Return if already     #calculated    if (dp[i][ones1][ones2][ones3] != -1):        return dp[i][ones1][ones2][ones3]     option1 = 0    option2 = 0    option3 = 0    option4 = 0    option5 = 0    option6 = 0    option7 = 0    option8 = 0     # Assigning 1's to all    # string at position 'i'.    if (ones1 > 0 and ones2 > 0 and        ones3 > 0):         # 2^(n-1-i) is the value        # added to the total        option1 = ((1 << ((n - 1) - i)) +                    maxXorValue(i + 1, s1,                                s2, s3,                                ones1 - 1,                                ones2 - 1,                                ones3 - 1, n))     # Assigning 1's to strings    # 1 & 2    if (ones1 > 0 and ones2 > 0 and       (n - i > ones3)):        option2 = (0 + maxXorValue(i + 1, s1,                                   s2, s3,                                   ones1 - 1,                                   ones2 - 1,                                   ones3, n))     # Assigning 1's to strings    # 2 & 3    if (ones2 > 0 and ones3 > 0 and       (n - i > ones1)):        option3 = (0 + maxXorValue(i + 1, s1,                                   s2, s3,                                   ones1,                                   ones2 - 1,                                   ones3 - 1, n))     # Assigning 1's to strings    # 3 & 1    if (ones3 > 0 and ones1 > 0 and       (n - i > ones2)):        option4 = (0 + maxXorValue(i + 1, s1,                                   s2, s3,                                   ones1 - 1,                                   ones2,                                   ones3 - 1, n))     # Assigning 1 to string 1    if (ones1 > 0 and (n - i > ones2)            and (n - i > ones3)):        option5 = ((1 << ((n - 1) - i))                   + maxXorValue(i + 1, s1,                                 s2, s3,                                 ones1 - 1,                                 ones2,                                 ones3, n))     # Assigning 1 to string 2    if (ones2 > 0 and (n - i > ones3) and       (n - i > ones1)):        option6 = ((1 << ((n - 1) - i)) +                    maxXorValue(i + 1, s1,                                s2, s3,                                ones1,                                ones2 - 1,                                ones3, n))     # Assigning 1 to string 3.    if (ones3 > 0 and (n - i > ones2) and        (n - i > ones1)):        option7 = ((1 << ((n - 1) - i)) +                    maxXorValue(i + 1, s1,                                s2, s3,                                ones1, ones2,                                ones3 - 1, n))     # Assigning 0 to all the strings    if ((n - i > ones2) and (n - i > ones3) and        (n - i > ones1)):        option8 = (0 + maxXorValue(i + 1, s1,                                   s2, s3,                                   ones1,                                   ones2,                                   ones3, n))     # Take the maximum amongst all of    # the above solutions    dp[i][ones1][ones2][ones3] = max(option1,                                 max(option2,                                 max(option3,                                 max(option4,                                 max(option5,                                 max(option6,                                 max(option7,                                 option8)))))))    return dp[i][ones1][ones2][ones3] # Function to get the count# of ones in the string sdef onesCount(s):       count = 0     # Traverse the string    for x in s:        if (x == '1'):            count += 1     # Return the count    return count # Utility Function to find# the maximum XOR value after# rearranging the digitsdef maxXORUtil(s1, s2,               s3, n):     # Find the count of ones in    # each of the strings    ones1 = onesCount(s1)    ones2 = onesCount(s2)    ones3 = onesCount(s3)     global dp     # Function Call    print(maxXorValue(0, s1, s2, s3,                      ones1, ones2,                      ones3, n)) # Driver codeif __name__ == "__main__":     s1 = "11110"    s2 = "10101"    s3 = "00111"    n = len(s1)     # Function Call    maxXORUtil(s1, s2, s3, n) # This code is contributed by Chitranayal
// C# program for the// above approachusing System;class GFG{ // Dp table to store// the sub-problemsstatic int[,,,] dp =       new int[20, 20,               20, 20];   // Function to find the// maximum XOR value after// rearranging the digitsstatic int maxXorValue(int i, String s1,                       String s2, String s3,                       int ones1, int ones2,                       int ones3, int n){      // Base Case  if (i >= n)    return 0;   // Return if already calculated  if (dp[i, ones1,         ones2, ones3] != -1)    return dp[i, ones1,              ones2, ones3];   int option1 = 0, option2 = 0,  option3 = 0, option4 = 0,  option5 = 0, option6 = 0,  option7 = 0, option8 = 0;   // Assigning 1's to all  // string at position 'i'.  if (ones1 > 0 && ones2 > 0 &&      ones3 > 0)     // 2^(n-1-i) is the value    // added to the total    option1 = (1 << ((n - 1) - i)) +               maxXorValue(i + 1, s1,                           s2, s3,                           ones1 - 1,                           ones2 - 1,                           ones3 - 1, n);   // Assigning 1's to  // strings 1 & 2  if (ones1 > 0 && ones2 > 0 &&     (n - i > ones3))    option2 = 0 + maxXorValue(i + 1, s1, s2,                              s3, ones1 - 1,                              ones2 - 1,                              ones3, n);   // Assigning 1's to strings 2 & 3  if (ones2 > 0 && ones3 > 0 &&     (n - i > ones1))    option3 = 0 + maxXorValue(i + 1, s1, s2,                              s3, ones1,                              ones2 - 1,                              ones3 - 1, n);   // Assigning 1's to strings 3 & 1  if (ones3 > 0 && ones1 > 0 &&     (n - i > ones2))    option4 = 0 + maxXorValue(i + 1, s1, s2,                              s3, ones1 - 1,                              ones2,                              ones3 - 1, n);   // Assigning 1 to string 1  if (ones1 > 0 && (n - i > ones2) &&     (n - i > ones3))    option5 = (1 << ((n - 1) - i)) +               maxXorValue(i + 1, s1,                           s2,s3,                           ones1 - 1,                           ones2, ones3, n);   // Assigning 1 to string 2  if (ones2 > 0 && (n - i > ones3) &&     (n - i > ones1))    option6 = (1 << ((n - 1) - i)) +               maxXorValue(i + 1, s1,                           s2, s3,                           ones1,                           ones2 - 1,                           ones3, n);   // Assigning 1 to string 3.  if (ones3 > 0 && (n - i > ones2) &&     (n - i > ones1))    option7 = (1 << ((n - 1) - i)) +               maxXorValue(i + 1, s1,                           s2, s3,                           ones1,                           ones2,                           ones3 - 1, n);   // Assigning 0 to all the strings  if ((n - i > ones2) &&      (n - i > ones3) &&      (n - i > ones1))    option8 = 0 + maxXorValue(i + 1,                              s1, s2,                              s3, ones1,                              ones2, ones3, n);   // Take the maximum amongst all of  // the above solutions  return dp[i, ones1,            ones2, ones3] = Math.Max(option1,                            Math.Max(option2,                            Math.Max(option3,                            Math.Max(option4,                            Math.Max(option5,                            Math.Max(option6,                            Math.Max(option7,                                     option8)))))));}   // Function to get the count// of ones in the string sstatic int onesCount(String s){  int count = 0;   // Traverse the string  foreach(char x in s.ToCharArray())  {    if (x == '1')      ++count;  }   // Return the count  return count;}   // Utility Function to find the maximum// XOR value after rearranging the digitsstatic void maxXORUtil(String s1, String s2,                       String s3, int n){    // Find the count of ones in  // each of the strings  int ones1 = onesCount(s1);  int ones2 = onesCount(s2);  int ones3 = onesCount(s3);   // Initialize dp table with -1  for(int i = 0; i < 20; i++)  {    for(int j = 0; j < 20; j++)    {      for(int l = 0; l < 20; l++)        for(int k = 0; k < 20; k++)          dp[i, j, l, k] =- 1;    }  }     // Function Call  Console.WriteLine(maxXorValue(0, s1, s2, s3,                                ones1, ones2,                                ones3, n));} // Driver codepublic static void Main(String[] args){  String s1 = "11110";  String s2 = "10101";  String s3 = "00111";   int n = s1.Length;   // Function call  maxXORUtil(s1, s2, s3, n);}} // This code is contributed by 29AjayKumar
<script> // Javascript program for the above approach // Dp table to store the sub-problemslet dp = new Array(20);for(let i = 0; i < 20; i++){    dp[i] = new Array(20);    for(let j = 0; j < 20; j++)    {        dp[i][j] = new Array(20);        for(let k = 0; k < 20; k++)        {            dp[i][j][k] = new Array(20);            for(let l = 0; l < 20; l++)            {                dp[i][j][k][l] = -1;            }        }    }} // Function to find the maximum XOR// value after rearranging the digitsfunction maxXorValue(i, s1, s2, s3, ones1,                     ones2, ones3, n){         // Base Case    if (i >= n)        return 0;        // Return if already calculated    if (dp[i][ones1][ones2][ones3] != -1)        return dp[i][ones1][ones2][ones3];        let option1 = 0, option2 = 0,        option3 = 0, option4 = 0,        option5 = 0, option6 = 0,        option7 = 0, option8 = 0;        // Assigning 1's to all string at    // position 'i'.    if (ones1 > 0 && ones2 > 0 &&        ones3 > 0)            // 2^(n-1-i) is the value        // added to the total        option1 = (1 << ((n - 1) - i)) +              maxXorValue(i + 1, s1, s2,                          s3, ones1 - 1,                              ones2 - 1,                              ones3 - 1, n);        // Assigning 1's to strings 1 & 2    if (ones1 > 0 && ones2 > 0 &&       (n - i > ones3))        option2 = 0 + maxXorValue(i + 1, s1, s2,                                  s3, ones1 - 1,                                      ones2 - 1,                                      ones3, n);        // Assigning 1's to strings 2 & 3    if (ones2 > 0 && ones3 > 0 &&       (n - i > ones1))        option3 = 0 + maxXorValue(i + 1, s1, s2,                                  s3, ones1,                                  ones2 - 1,                                  ones3 - 1, n);        // Assigning 1's to strings 3 & 1    if (ones3 > 0 && ones1 > 0 &&       (n - i > ones2))        option4 = 0 + maxXorValue(i + 1, s1, s2,                                  s3, ones1 - 1,                                  ones2,                                  ones3 - 1, n);        // Assigning 1 to string 1    if (ones1 > 0 && (n - i > ones2) &&       (n - i > ones3))        option5 = (1 << ((n - 1) - i)) +                   maxXorValue(i + 1, s1, s2,                               s3, ones1 - 1,                               ones2, ones3, n);        // Assigning 1 to string 2    if (ones2 > 0 && (n - i > ones3) &&       (n - i > ones1))        option6 = (1 << ((n - 1) - i)) +                   maxXorValue(i + 1, s1,                               s2, s3, ones1,                               ones2 - 1,                               ones3, n);        // Assigning 1 to string 3.    if (ones3 > 0 && (n - i > ones2) &&       (n - i > ones1))        option7 = (1 << ((n - 1) - i)) +                  maxXorValue(i + 1, s1,                              s2, s3, ones1,                              ones2,                              ones3 - 1, n);        // Assigning 0 to all the strings    if ((n - i > ones2) && (n - i > ones3) &&        (n - i > ones1))        option8 = 0 + maxXorValue(i + 1, s1,                                  s2, s3, ones1,                                  ones2, ones3, n);        // Take the maximum amongst all of    // the above solutions    return dp[i][ones1][ones2][ones3] =        Math.max(option1,                 Math.max(option2,                     Math.max(option3,                        Math.max(option4,                             Math.max(option5,                                 Math.max(option6,                                     Math.max(option7,                                              option8)))))));} // Function to get the count of ones// in the string sfunction onesCount(s){    let count = 0;        // Traverse the string    for(let x = 0; x < s.length; x++)    {        if (s[x] == '1')            ++count;    }        // Return the count    return count;} // Utility Function to find the maximum// XOR value after rearranging the digitsfunction maxXORUtil(s1, s2, s3, n){         // Find the count of ones in    // each of the strings    let ones1 = onesCount(s1);    let ones2 = onesCount(s2);    let ones3 = onesCount(s3);         // Function Call    document.write(maxXorValue(0, s1, s2, s3,                               ones1, ones2,                               ones3, n));} // Driver codelet s1 = "11110";let s2 = "10101";let s3 = "00111";let n = s1.length; // Function callmaxXORUtil(s1, s2, s3, n); // This code is contributed by avanitrachhadiya2155 </script>
30
Time Complexity: O(N4)Auxiliary Space: O(N)
offbeat
29AjayKumar
ukasp
avanitrachhadiya2155
binary-string
Bitwise-XOR
Permutation and Combination
Bit Magic
Combinatorial
Dynamic Programming
Mathematical
Strings
Strings
Dynamic Programming
Mathematical
Bit Magic
Combinatorial
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Little and Big Endian Mystery
Cyclic Redundancy Check and Modulo-2 Division
Binary representation of a given number
Add two numbers without using arithmetic operators
Josephus problem | Set 1 (A O(n) Solution)
Write a program to print all permutations of a given string
Permutation and Combination in Python
Factorial of a large number
itertools.combinations() module in Python to print all possible combinations