通过执行子字符串的异或运算,在 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) 用于存储临时字符串。