通过执行子字符串的异或运算,在 K 步内最大化二进制字符串的值


在这个问题中,我们将通过对给定二进制字符串的子字符串执行 K 次异或运算来最大化二进制字符串的值。

为了最大化任何二进制字符串,我们应该最大化从最左侧零开始的子字符串。例如,要最大化字符串“11001”,我们需要选择另一个子字符串,以便我们可以最大化“001”子字符串。

问题陈述

我们给定一个名为 bin_str 的二进制字符串,包含 N 个字符。我们必须通过对任何两个子字符串执行异或运算,在 K 次操作中最大化二进制字符串的值。给定子字符串可以是相同、相交或不相交的。

示例

输入

bin_str = "1101"; K = 1;

输出

1111

解释

我们可以取 10 和 1101 子字符串,当我们对两者执行异或运算时,我们得到最大字符串 1111。

输入

bin_str = "110101"; K = 2

输出

111110

解释

  • 在第一次操作中,我们可以取 110101 和 1010 子字符串。当我们对这两个字符串执行异或运算时,我们得到二进制字符串 111111。

  • 在第二次操作中,我们可以取 111111 和 1 子字符串,当我们对两者执行异或运算时,我们得到 111110,这是我们可以得到的最大字符串。

输入

bin_str = "01"; K = 1;

输出

1

解释

取 01 和 0 子字符串得到 1。

方法 1

在这种方法中,我们将从最左侧的 0 到末尾取一个子字符串,并找到字符串的另一个子字符串以获得最大的二进制字符串值。

例如,二进制字符串是 1110010101。要最大化二进制字符串,我们需要最大化 0010101 子字符串。因此,我们将取二进制字符串本身作为第一个子字符串,并取相同长度的另一个字符串“0010101”来最大化二进制字符串。

算法

  • 步骤 1 - 对 K 次执行 maxValUtil() 函数,并使用其返回值更新二进制字符串。

  • 步骤 2 - 在 maxValUtil() 函数中,将“leftZero”初始化为 -1 以存储最左侧零的索引,“cnt0”和“cnt1”初始化为 0 以分别存储二进制字符串中 0 和 1 的数量。

  • 步骤 3 - 遍历字符串,如果当前字符是“1”,则将“cnt1”加 1。否则,如果“leftZero”是 -1,则将其值更新为当前索引并将“cnt0”值加 1。

  • 步骤 4 - 如果“cnt1”和“len”相等,则取二进制字符串与“1”的异或,并返回其值。

  • 步骤 4.1 - 在 getXOR() 函数中获取两个字符串的长度。如果两个字符串长度不相等,则通过执行 addZeros() 函数在长度较小的字符串前面添加零。

  • 步骤 4.1.1 - 在 addZero() 函数中,在字符串的开头附加所需的零。

  • 步骤 4.2 - 初始化“XOR”字符串以存储对两个字符串执行异或运算后的结果。

  • 步骤 4.3 - 遍历两个字符串,如果两个字符串中第 p 个索引处的字符相同,则将“0”附加到 XOR 字符串。否则,将“1”附加到 XOR 字符串。

  • 步骤 4.4 - 返回 XOR 字符串。

  • 步骤 5 - 在 maxValUtil() 函数中,如果“cnt0”等于二进制字符串的长度,则返回“0”。

  • 步骤 6 - 使用 substr() 方法初始化“rightStr”字符串,该字符串从“leftZero”索引开始。还将“size”初始化为“rightStr”字符串的大小,“temp”初始化为“rightStr”字符串,“maxRes”、“temp1”和“temp2”初始化为空字符串。

  • 步骤 7 - 开始遍历二进制字符串。如果索引小于“size”变量的值,则将字符附加到“temp1”字符串。

  • 步骤 8 - 否则,获取“temp”和“temp1”字符串的异或。如果异或值超过“maxRes”字符串的值,则将“maxRes”更新为“res”并将“temp2”更新为“temp1”。此外,从“temp1”字符串中删除第一个字符,并在末尾附加当前字符。

在这里,我们找到“temp2”子字符串,使得“temp1”和“temp2”的异或最大化,以最大化二进制字符串。

  • 步骤 9 - 处理我们取 temp1 字符串与 rightStr 字符串的异或的最后一个情况。

  • 步骤 10 - 接下来,取二进制字符串和 temp2 字符串的异或,并将结果存储在答案中。

  • 步骤 11 - 删除前导零后返回“answer”字符串。

示例

以下是上述算法的程序 -

#include <stdio.h>
#include <string.h>
#include <stdlib.h> // Added for dynamic memory allocation

// Function to add 'n' zeros to the beginning of a string
void addNZero(char *substr, int n) {
   int i;

   // Shift existing characters to the right to make space for zeros
   for (i = strlen(substr); i >= 0; i--) {
      substr[i + n] = substr[i];
   }

   // Add 'n' zeros at the beginning
   for (i = 0; i < n; i++) {
      substr[i] = '0';
   }
}

// Function to perform XOR of two strings
void getXOR(char *temp1, char *temp2, char *result) {
   int len1 = strlen(temp1);
   int len2 = strlen(temp2);
   int len = len1 > len2 ? len1 : len2; // Maximum length
   int i;

   // Make both strings of equal length by adding leading zeros
   if (len1 > len2) {
      addNZero(temp2, len1 - len2);
   } else if (len2 > len1) {
      addNZero(temp1, len2 - len1);
   }

   // Compute XOR
   for (i = 0; i < len; i++) {
      if (temp1[i] == temp2[i]) {
         result[i] = '0';
      } else {
         result[i] = '1';
      }
   }

   // Null-terminate the result string
   result[len] = '\0';
}

// Function to find the maximum value of a binary string after K XOR operations
void findMaxValue(char *bin_str, int K) {
   int len = strlen(bin_str);
   int leftZero = -1, cnt0 = 0, cnt1 = 0;
   char *rightStr, *temp, *maxRes, *temp1, *temp2;
   int size;

   // Calculate the number of 0's and 1's in the binary string
   for (int p = 0; p < len; p++) {
      if (bin_str[p] == '1') {
         cnt1++;
      } else {
         if (leftZero == -1) {
            leftZero = p;
         }
         cnt0++;
      }
   }

   // Case 1 - When the string contains all 1's
   if (cnt1 == len) {
      char one[] = "1";
      getXOR(bin_str, one, bin_str);
      return;
   }

   // Case 2 - When the string contains all zeros
   if (cnt0 == len) {
      printf("0\n");
      return;
   }

   // Take the substring starting from the leftmost '0' to maximize it
   rightStr = bin_str + leftZero;
   size = len - leftZero;
   temp = rightStr;
   maxRes = (char *)malloc((len + 1) * sizeof(char)); // Allocate memory for maxRes
   temp1 = (char *)malloc((len + 1) * sizeof(char));   // Allocate memory for temp1
   temp2 = (char *)malloc((len + 1) * sizeof(char));   // Allocate memory for temp2

   // Initialize memory to avoid undefined behavior
   memset(maxRes, 0, (len + 1) * sizeof(char));
   memset(temp1, 0, (len + 1) * sizeof(char));
   memset(temp2, 0, (len + 1) * sizeof(char));

   // Choosing the second string
   for (int q = 0; q < len; q++) {
      if (q < size) {
         temp1[q] = bin_str[q];
      } else {
         // If temp1 gives the maximum XOR result, choose it as the second string
         char res[len + 1];
         getXOR(temp, temp1, res);
         if (strcmp(res, maxRes) > 0) {
            strcpy(maxRes, res);
            strcpy(temp2, temp1);
         }

         // Update temp1 string
         for (int i = 0; i < size - 1; i++) {
            temp1[i] = temp1[i + 1];
         }
         temp1[size - 1] = bin_str[q];
      }
   }

   // Handling the last case
   char res[len + 1];
   getXOR(temp1, temp, res);
   if (strcmp(res, maxRes) > 0) {
      strcpy(maxRes, res);
      strcpy(temp2, rightStr);
   }

   // Take the XOR of the original string and the second string
   getXOR(bin_str, temp2, bin_str);

   // Remove leading zeros
   leftZero = -1;
   for (int p = 0; p < len; p++) {
      if (bin_str[p] != '0') {
         leftZero = p;
         break;
      }
   }
   if (leftZero == -1) {
      printf("0\n");
   } else {
      printf("%s\n", bin_str + leftZero);
   }

   // Free dynamically allocated memory
   free(maxRes);
   free(temp1);
   free(temp2);
}

int main() {
   char bin_str[] = "1101";
   int K = 1;
   printf("The maximum value of the string after performing 1 XOR operations is - ");
   findMaxValue(bin_str, K);
   return 0;
}

输出

The maximum value of the string after performing 1 XOR operations is - 1111
#include <bits/stdc++.h>
using namespace std;

void addNZero(string &substr, int n) {
   // Adding the initial '0' to the string to make its length the same as the other sub string
   for (int p = 0; p < n; p++) {
      substr = "0" + substr;
   }
}

// Finding XOR of two strings
string getXOR(string temp1, string temp2) {  

   // Get string sizes
   int temp1_len = temp1.length();
   int temp2_len = temp2.length();
   
   // Append zeros to the smaller string
   if (temp1_len > temp2_len) {
      addNZero(temp2, temp1_len - temp2_len);
   } else if (temp2_len > temp1_len) {
      addNZero(temp1, temp2_len - temp1_len);
   }
   
   // Final string length
   int len = max(temp1_len, temp2_len);
   
   // To store the resultant XOR
   string XOR = "";
   
   // Take XOR of both strings
   for (int p = 0; p < len; p++) {
      if (temp1[p] == temp2[p])
         XOR += "0";
      else
         XOR += "1";
   }
   return XOR;
}
string maxValUtil(string bin_str) {

   // String length
   int len = bin_str.size();
   int leftZero = -1, cnt0 = 0, cnt1 = 0;
   
   // Calculate number of 0's and 1's in the given string.
   for (int p = 0; p < len; p++) {
      if (bin_str[p] == '1') {
         cnt1++;
      } else {
      
         // For the left most '0'
         if (leftZero == -1) {
            leftZero = p;
         }
         cnt0++;
      }
   }
   
   // Case 1 - When the string contains all 1's
   if (cnt1 == len) {
      return getXOR(bin_str, "1");
   }
   
   // Case 2 - When the string contains all zeros
   if (cnt0 == len) {
      return "0";
   }
   
   // Take the substring starting from left most '0' as we need to maximize it
   string rightStr = bin_str.substr(leftZero, len - leftZero);
   int size = rightStr.size();
   string temp = rightStr;
   string maxRes = "";
   string temp1 = "", temp2 = "";
   
   // Choosing the second string
   for (int q = 0; q < len; q++) {
   
      // Finding the substring of length 'size' from start
      if (q < size) {
      temp1 += bin_str[q];
      } else {
      
         // If temp1 gives the maximum XOR result, choose it as a second string
         string res = getXOR(temp, temp1);
         if (res > maxRes) {
            maxRes = res;
            temp2 = temp1;
         }
         
         // Update temp1 string
         temp1 = temp1.substr(1);
         temp1 += bin_str[q];
      }
   }
   
   // Handling the last case
   string res = getXOR(temp1, temp);
   if (res > maxRes) {
      maxRes = res;
      temp2 = rightStr;
   }
   
   // Take the XOR of the original string and the second string
   string answer = getXOR(bin_str, temp2);
   leftZero = -1;
   for (int p = 0; p < answer.size(); p++) {
   
      // Remove initial zeros
      if (answer[p] != '0') {
         leftZero = p;
         break;
      }
   }
   if (leftZero == -1) {
      return "0";
   }
   
   // Final maximum string
   return answer.substr(leftZero);
}
string findMaxValue(string bin_str, int K) {

   // Find the maximum value of the updated binary string
   for (int p = 0; p < K; p++) {
      bin_str = maxValUtil(bin_str);
   }
   return bin_str;
}
int main() {
   string bin_str = "1101";
   int K = 1;
   cout << "The maximum value of the string after performing " << K << " XOR operations is - " << findMaxValue(bin_str, K) << endl;
   return 0;
}

输出

The maximum value of the string after performing 1 XOR operations is - 1111
public class Main {
   // Function to calculate XOR of two strings
   public static String getXOR(String temp1, String temp2) {
      int len1 = temp1.length();
      int len2 = temp2.length();
      int length = Math.max(len1, len2);

      // Add leading zeros to the shorter string
      if (len1 > len2) {
         temp2 = "0".repeat(len1 - len2) + temp2;
      } else if (len2 > len1) {
         temp1 = "0".repeat(len2 - len1) + temp1;
      }

      StringBuilder XOR = new StringBuilder();

      // Perform XOR of both strings
      for (int i = 0; i < length; i++) {
         XOR.append(temp1.charAt(i) == temp2.charAt(i) ? '0' : '1');
      }

      return XOR.toString();
   }

   // Function to find the maximum value substring
   public static String maxValUtil(String bin_str) {
      int length = bin_str.length();
      int leftZero = -1;
      int cnt0 = 0, cnt1 = 0;

      // Count the number of 0's and 1's in the binary string
      for (int i = 0; i < length; i++) {
         if (bin_str.charAt(i) == '1') {
            cnt1++;
         } else {
            if (leftZero == -1) {
               leftZero = i;
            }
            cnt0++;
         }
      }

      // Case 1: All 1's in the string
      if (cnt1 == length) {
         return getXOR(bin_str, "1");
      }

      // Case 2: All 0's in the string
      if (cnt0 == length) {
         return "0";
      }

      // Find the substring starting from the leftmost '0'
      String rightStr = bin_str.substring(leftZero);
      int size = rightStr.length();
      String temp = rightStr;
      String maxRes = "";
      String temp1 = "";
      String temp2 = "";

      // Choosing the second string
      for (int i = 0; i < length; i++) {
         if (i < size) {
            temp1 += bin_str.charAt(i);
         } else {
            String res = getXOR(temp, temp1);
            if (res.compareTo(maxRes) > 0) {
               maxRes = res;
               temp2 = temp1;
            }
            temp1 = temp1.substring(1) + bin_str.charAt(i);
         }
      }

      // Handling the last case
      String res = getXOR(temp1, temp);
      if (res.compareTo(maxRes) > 0) {
         maxRes = res;
         temp2 = rightStr;
      }

      // Take the XOR of the original string and the second string
      String answer = getXOR(bin_str, temp2);
      leftZero = -1;

      // Remove leading zeros
      for (int i = 0; i < answer.length(); i++) {
         if (answer.charAt(i) != '0') {
            leftZero = i;
            break;
         }
      }

      if (leftZero == -1) {
         return "0";
      }

      // Final maximum string
      return answer.substring(leftZero);
   }

   // Function to find the maximum value of the binary string after K XOR operations
   public static String findMaxValue(String bin_str, int K) {
      for (int i = 0; i < K; i++) {
         bin_str = maxValUtil(bin_str);
      }
      return bin_str;
   }

   public static void main(String[] args) {
      String bin_str = "1101";
      int K = 1;
      String result = findMaxValue(bin_str, K);
      System.out.println("The maximum value of the string after performing " + K + " XOR operations is - " + result);
   }
}

输出

The maximum value of the string after performing 1 XOR operations is - 1111
def addNZero(substr, n):
   for _ in range(n):
      substr = '0' + substr

# Finding XOR of two strings
def getXOR(temp1, temp2):
   # Get string sizes
   temp1_len = len(temp1)
   temp2_len = len(temp2)

   # Append zeros to the smaller string
   if temp1_len > temp2_len:
      temp2 = '0' * (temp1_len - temp2_len) + temp2
   elif temp2_len > temp1_len:
      temp1 = '0' * (temp2_len - temp1_len) + temp1

   # Final string length
   length = max(temp1_len, temp2_len)

   # Take XOR of both strings
   result = ''
   for p in range(length):
      if temp1[p] == temp2[p]:
         result += '0'
      else:
         result += '1'
   return result

def maxValUtil(bin_str):
   # String length
   length = len(bin_str)
   leftZero = -1
   cnt0 = 0
   cnt1 = 0

   # Calculate the number of 0's and 1's in the given string.
   for p in range(length):
      if bin_str[p] == '1':
         cnt1 += 1
      else:
         # For the leftmost '0'
         if leftZero == -1:
            leftZero = p
         cnt0 += 1

   # Case 1 - When the string contains all 1's
   if cnt1 == length:
      return getXOR(bin_str, '1')

   # Case 2 - When the string contains all zeros
   if cnt0 == length:
      return '0'

   # Take the substring starting from the leftmost '0' as we need to maximize it
   rightStr = bin_str[leftZero:]
   size = len(rightStr)
   temp = rightStr
   maxRes = ''
   temp1 = ''
   temp2 = ''

   # Choosing the second string
   for q in range(length):
      # Finding the substring of length 'size' from start
      if q < size:
         temp1 += bin_str[q]
      else:
         # If temp1 gives the maximum XOR result, choose it as the second string
         res = getXOR(temp, temp1)
         if res > maxRes:
            maxRes = res
            temp2 = temp1

         # Update temp1 string
         temp1 = temp1[1:] + bin_str[q]

   # Handling the last case
   res = getXOR(temp1, temp)
   if res > maxRes:
      maxRes = res
      temp2 = rightStr

   # Take the XOR of the original string and the second string
   answer = getXOR(bin_str, temp2)
   leftZero = -1
   for p in range(len(answer)):
      # Remove initial zeros
      if answer[p] != '0':
         leftZero = p
         break
   if leftZero == -1:
      return '0'

   # Final maximum string
   return answer[leftZero:]

def findMaxValue(bin_str, K):
   # Find the maximum value of the updated binary string
   for _ in range(K):
      bin_str = maxValUtil(bin_str)
   return bin_str

bin_str = '1101'
K = 1
result = findMaxValue(bin_str, K)
print(f"The maximum value of the string after performing {K} XOR operations is - {result}")

输出

The maximum value of the string after performing 1 XOR operations is - 1111

时间复杂度 – O(N*N*K),其中 O(N) 用于查找最大化二进制字符串的子字符串,另一个 O(N) 用于执行两个字符串的异或运算,O(K) 用于执行总共 K 次操作。

空间复杂度 – O(N) 用于存储临时字符串。

更新于: 2023-10-23

247 次浏览

开启你的 职业生涯

通过完成课程获得认证

开始学习
广告