XORMAX - Editorial

PROBLEM LINK:

Practice
Contest: Division 1
Contest: Division 2
Contest: Division 3
Contest: Division 4

Author: utkarsh_25dec
Testers: IceKnight1093, tejas10p
Editorialist: IceKnight1093

DIFFICULTY:

1229

PREREQUISITES:

None

PROBLEM:

Given two binary strings A and B, find the maximum possible value of A\oplus B if both strings can be rearranged as you wish.

EXPLANATION:

Since we’d like to maximize the xor, we’d like to have as many 1's as possible.

We can obtain a 1 by:

  • Pairing a 0 in A with a 1 in B
  • Pairing a 1 in A with a 0 in B

Now, let A_0 and A_1 be the count of 0's and 1's in A. Similarly define B_0 and B_1.

Notice that we can obtain at most \min(A_0, B_1) ones of the first type, and \min(A_1, B_0) ones of the second type.
Of course, it’s always possible to attain exactly these many ones since they’re independent.

So, our final string has \min(A_0, B_1) + \min(A_1, B_0) ones, and then every other character is 0.
To maximize the xor, place all the ones before the zeroes.

TIME COMPLEXITY:

\mathcal{O}(N) per testcase.

CODE:

Code (Python)
for _ in range(int(input())):
    a = input()
    b = input()
    n = len(a)
    a0, a1 = a.count('0'), a.count('1')
    b0, b1 = b.count('0'), b.count('1')
    ones = min(a0, b1) + min(a1, b0)
    print('1'*ones + '0'*(n - ones))
2 Likes

Why am I getting time limit exceeded?

#include <bits/stdc++.h>
using namespace std;

void solution()
{
    string A, B, C = "";
	cin >> A >> B;
	int one = 0, zero = 0, length = A.length();
	for(int i = 0; i < length; i++)
	{
	    if(A[i] == '1')
	    {
	        one++;
	    }
	    else
        {
            zero++;
        }
        if(B[i] == '1')
        {
            one++;
        }
        else
        {
            zero++;
        }
	}
	int X = min(one, zero);
	for(int i = 0; i < X; i++)
	{
	    C = C + '1';
	}
	for (int i = 0; i<length - X; i++)
	{
	    C = C + '0';
	}
	cout << C<< endl;
}

int main() {
	// your code goes here
	int T;
	cin >> T;
	while(T--)
	{
        solution();
	}
	return 0;
}

Your code has complexity \mathcal{O}(N^2) because C = C + '1'; (and C = C + '0';) take \mathcal{O}(N) time, not \mathcal{O}(1).

Instead use C += '1' and C += '0'

4 Likes

Thanks for your answer, the problem is solved. However, I have looked through Google about this and most of the answers say that x +=1 and x= x+1 are same. Please explain the time complexity of these two in short.

a += b and a = a + b are actually slightly different things if you look at what the operators mean.

a += b means "apply the += operator on a and b. For integers, this means adding b to a. For strings, this means appending b to a (notice that it modifies a, but doesn’t need to touch the existing characters in a).

a = a + b means "create the value a + b, then assign it to a".
For integers, this isn’t a problem because creating the value a + b is easy, but it’s a problem for strings, since you create an entirely new string each time you append something.

For example, say you append c N times to an empty string S one by one using S = S + 'c'

  • In the first iteration, it creates the string c, then assigns it to S
  • In the second iteration, it creates the string cc then assigns it to S
  • In the third iteration, it creates the string ccc then assigns it to S
    \vdots

It’s easy to see that the total length of strings you create is 1 + 2 + 3 + \ldots + N = N(N+1)/2

You can test this yourself easily, just try running the code

string s = "";
for (int i = 0; i < 1000000; ++i) s += '0';

then replace the statement with s = s + '0' and see what happens.

5 Likes

Thanks for the explanation.

The s += ‘0’ code runs fast whereas s = s + ‘0’ takes a loooong time and throws SIGTSTP

What is wrong with this code ?
It has passed all test cases for Sample 1 , but overall Result is WA

#include <bits/stdc++.h>
using namespace std;

string max_xor(string s1,string s2){
    int cnt_0=0,cnt_1=0;
    int n=s1.size();
    string s3="";
    for(int i=0;i<n;i++){
        if(s2[i]=='1')
            cnt_1++;
        else
            cnt_0++;
    }
    for(int i=0;i<n;i++){
        
        if(s1[i]=='1'){
            if(cnt_0>0)
            {
                cnt_0--;
                s3+='1';
            }
            else
                s3+='0';
        }
        else
        {
            if(cnt_1>0)
            {
                cnt_1--;
                s3+='1';
            }
            else
                s3+='0';
        }
    }
    return s3;
}

int main() {
	int T;
	cin>>T;
	while(T--){
	    string A,B;
	    cin>>A>>B;
	    cout<<max_xor(A,B)<<endl;
	}
	return 0;
}

Consider

1
101
000

where your code prints 101 but the answer is 110.
You’re correctly computing the number of ones in the answer, they just might not be in the right positions.

Thanks a lot, for solving my query and providing the test case.
So to get all 1 at correct place we can use sorting [ Using 2 pointers to avoid Runtime error] in the final string.
OR
what else can we do to make this code work ? , other than using the same solution as in editorial.