透過執行子字串的異或運算,在 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 次瀏覽

開啟你的 職業生涯

透過完成課程獲得認證

開始學習
廣告
© . All rights reserved.