Data Structure
Networking
RDBMS
Operating System
Java
MS Excel
iOS
HTML
CSS
Android
Python
C Programming
C++
C#
MongoDB
MySQL
Javascript
PHP
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
Maximize value of Binary String in K steps by performing XOR of Substrings
In this problem, we will maximize the value of the binary string by performing K XOR operations of substrings of the given binary string.
To maximize any binary string, we should maximize the substring starting from the leftmost zero. For example, to maximize the ?11001' string, we need to choose another substring in such a way that we can maximize the ?001' substring.
Problem Statement
We have given a binary string named bin_str containing N characters. We have to maximize the value of the binary string in K operations by taking the XOR operation of any two substrings. It is given that substrings can be the same, intersecting or non-intersecting.
Sample Examples
Input
bin_str = "1101"; K = 1;
Output
1111
Explanation
We can take 10 and 1101 substrings, and when we perform XOR of both, we get the 1111 maximum string.
Input
bin_str = "110101"; K = 2
Output
111110
Explanation
In the first operation, we can take 110101 and 1010 substrings. Whesubstringrm XOR operation of both strings, we get 111111 binary string.
In the second operation, we can take 111111 and 1 substring, and when we perform the XOR operation of both, we get 111110, the maximum string we can get.
Input
bin_str = "01"; K = 1;
Output
1
Explanation
Take 01 and 0 substrings to get 1.
Approach 1
In this approach, we will take a substring from the leftmost 0 to the end and find another substring of the string to get the maximum binary string value.
For example, the binary string is 1110010101. To maximize the binary string, we need to maximize the 0010101 substrings. So, we will take the binary string itself as one substring and another string of the same length, ?0010101,' to maximize the binary string.
Algorithm
Step 1 ? Execute the maxValUtil() function for K times, and update the binary string with its returned value.
Step 2 ? In the maxValUtil() function, Initialize the ?leftZero' with -1 to store the index of the leftmost zero, ?cnt0' and ?cnt1' with 0 to store the count of 0 and 1 in the binary string, respectively.
Step 3 ? Traverse the string, and if the current character is ?1', increment the ?cnt1' by 1. Otherwise, if ?leftZero' is -1, update its value with the current index and increment the ?cnt0' value.
Step 4 ? If ?cnt1' and ?len' is equal, take the XOR of a binary string with ?1' and return its value.
Step 4.1 ? Take the length of both strings in the getXOR() function. If both strings are not of the same length, add the zeros to the string with the smallest length by executing the addZeros() function.
Step 4.1.1 ? In the addZero() function, append the required zeros at the start of the string.
Step 4.2 ? Initialize the ?XOR" string to store the result after performing the XOR operation of both strings.
Step 4.3 ? Traverse both strings and if the character at the pth index in both strings is the same, append ?0' to the XOR string. Otherwise, append ?1' to the XOR string.
Step 4.4 ? Return the XOR string.
Step 5 ? In the maxValUtil() function, if ?cnt0' is equal to the binary string's length, return ?0'.
Step 6 ? Initialize the ?rightStr' string with the substring starting from the ?leftZero' index using the substr() method. Also, initialize the ?size' with the ?rightStr' string's size, temp with the ?rightStr' string, ?maxRes', ?temp1', and ?temp2' with an empty string.
Step 7 ? Start traversing the binary string. If the index is less than the ?size' variable's value, append a character to the ?temp1' string.
Step 8 ? Else, Get the XOR of the ?temp' and ?temp1' strings. If the XOR value exceeds the ?maxRes' string's value, update the ?maxRes' with ?res' and ?temp2' with ?temp1'. Also, remove the first character from the ?temp1' string and append the current character at last.
Here, we find the ?temp2' substring such that the XOR of ?temp1' and ?temp2' becomes maximum to maximize the binary string.
Step 9 ? Handle the last case in which we take XOR of temp1 string with rightStr string.
SStep 10 ? Next, take the XOR of the binary string and temp2 string, and store the result in the answer.
Step 11 ? Return the ?answer' string after removing the leading zeros.
Example
Following are the Programs to the above algorithm
#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;
}
Output
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;
}
Output
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);
}
}
Output
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}")
Output
The maximum value of the string after performing 1 XOR operations is - 1111
Time complexity - O(N*N*K), where O(N) is for finding substring to maximize binary string, another O(N) is to perform the XOR operation of two strings, and O(K) is to perform total K operations.
Space complexity - O(N) to store the temporary strings.