📌  相关文章
📜  重新排列给定的二进制字符串以最大化其按位XOR值

📅  最后修改于: 2021-04-26 05:50:53             🧑  作者: Mango

给定三个二进制字符串S1S2S3,每个字符串的长度为N ,任务是找到可以通过重新排列给定字符串的字符而获得的最大可能的按位XOR。

例子:

天真的方法:最简单的方法是生成所有可能的方法来重新排列S1S2S3 。假设在字符串S1S2S3中分别有O1O2O3设置位。要获得最大按位XOR值,要检查的重排总数如下:

时间复杂度: O((N!) 3 ),其中N是给定字符串的长度。
辅助空间: O(N)

高效的方法:想法是找到合适的S1S2S3重排,以便使用动态编程使它们的按位XOR值最大化。子问题可以存储在dp [] [] [] []表中,其中dp [i] [o1] [o2] [o3]存储最大XOR值,从索引i开始直到位置N-1 ,其中o1 o2o3是分别剩下要放置在字符串S1S2S3中1 s的数目。

0(N – 1)的任何位置i可能有四种情况:

  1. 给所有三个字符串分配1 s
  2. 1 s分配给任意两个字符串
  3. 1 s分配给任意一个字符串。
  4. 0分配给所有字符串。

从上述每个位置的可能情况中,计算从四种可能性中可获得的最大按位异或:

请按照以下步骤解决问题:

  • 初始化表dp [] [] [] []以存储位置i0到N-1的S1S2S3中的个数。
  • 过渡状态如下:
  • 使用上述转换解决所有情况的子问题,并在其中打印最大XOR值。

下面是上述方法的实现:

C++
// C++ program for the above approach
 
#include 
using namespace std;
 
// Dp table to store the sub-problems
int dp[20][20][20][20];
 
// Function to find the maximum XOR
// value after rearranging the digits
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]
           = 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 s
int 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 digits
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
    memset(dp, -1, sizeof dp);
 
    // Function Call
    cout << maxXorValue(0, s1, s2, s3,
                        ones1, ones2,
                        ones3, n);
}
 
// Driver code
int main()
{
    string s1 = "11110";
    string s2 = "10101";
    string s3 = "00111";
 
    int n = s1.size();
 
    // Function Call
    maxXORUtil(s1, s2, s3, n);
 
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
import java.lang.*;
class GFG{
 
// Dp table to store the sub-problems
static int[][][][]  dp = new int[20][20][20][20];
   
// Function to find the maximum XOR
// value after rearranging the digits
static 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 s
static 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 digits
static 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 code
public 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
# Python3 program for the
# above approach
 
# Dp table to store the
# sub-problems
dp = [[[[-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 digits
def 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 s
def 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 digits
def 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 code
if __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#
// C# program for the
// above approach
using System;
class GFG{
 
// Dp table to store
// the sub-problems
static int[,,,] dp =
       new int[20, 20,
               20, 20];
   
// Function to find the
// maximum XOR value after
// rearranging the digits
static 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 s
static 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 digits
static 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 code
public 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


输出
30

时间复杂度: O(N 4 )
辅助空间: O(N)