📜  范围内非常大的二进制数的异或 [L, R]

📅  最后修改于: 2022-05-13 01:56:07.364000             🧑  作者: Mango

范围内非常大的二进制数的异或 [L, R]

给定两个二进制字符串LR ,任务是找到从 L 到 R 的异或。二进制字符串的长度是< = 10e6

例子:

朴素方法:解决问题的最简单方法是找到范围[L, R]中的所有二进制字符串,然后对所有二进制字符串执行 XOR 操作。

时间复杂度: (R – L +1) *(N) 其中 N 是二进制字符串R 的长度。
辅助空间: O(1)

有效的方法:上述方法可以通过观察进一步优化 -

  • (L ^ (L+1) ^……^(R – 1) ^ R)可以写成(1^2^3 ^…. ^(R-1)^R) ^ (1^2^3 … .. ^(L-2) ^ (L-1))其中“^”表示元素的按位异或。所以问题被简化为找到从 1 到 n 的异或。
  • 要计算从 1 到 n 的异或,通过用4n取模来找到 n 的余数,并将其存储在一个变量中,比如remrem有四个可能的值——
    • 如果rem =0xor = n
    • 如果rem = 1那么xor = 1
    • 如果rem = 2那么xor = n+1
    • 如果rem = 3那么xor = 0

观察以上几点后,按照以下步骤解决问题:

  • 通过执行下面提到的步骤,创建一个从大小为 N 的二进制字符串S 中减去 1 的函数sub
    • 使用变量i[N-1, 0]范围内迭代并执行以下步骤:
      • 如果S[i] = '0' ,则将S[i]的值修改为1。
      • 如果S[i] = '1' ,则将S[i]的值修改为0并终止循环。
    • 返回字符串S作为答案。
  • 通过执行下面提到的步骤,创建一个函数ad ,将 1 加到大小为 N 的二进制字符串S 上:
    • 初始化一个变量,比如进位0
    • 使用变量i[N-1, 0]范围内迭代并执行以下步骤:
      • 如果S[i] = '1' ,则将S[i]的值修改为0并将进位的值修改为1
      • 如果S[i] = '0' ,则将S[i]的值修改为1并将进位的值修改为0并终止循环。
    • 如果进位 =1 ,则将S的值修改为'1' + S并返回字符串S
  • 创建一个函数Xor_Finder ,通过执行以下步骤将 XOR 的值从1返回到S
    • 初始化一个变量,比如val并将值更新为S[n] + S[n-1]*2其中 n 是字符串S 的长度。
    • 现在如果val = 0 ,则返回字符串S作为答案。
    • 如果val = 1 ,则返回 '1' 作为答案。
    • 如果val = 2 ,则返回ad(S)作为答案。
    • 如果val = 3 ,则返回 0 作为答案。
  • 创建一个函数final_xor ,通过执行下面提到的步骤计算两个二进制字符串L 和 R 的异或:
    • L.size() != R.size()时将字符'0' 附加到字符串L中。
    • 初始化一个字符串,比如说ans ,它将存储二进制字符串LR的 xor 值。
    • 使用变量i[0, R.size()-1]范围内迭代并执行以下步骤:
      • 如果L[i] = R[i] ,则在字符串ans 的末尾附加字符'0'。
      • 如果L[i] != R[i] ,则将字符'1' 附加到字符串ans 的末尾。
    • 返回字符串ans作为两个字符串的异或。
  • 通过执行以下步骤,创建一个函数xorr以计算从LR的 xor:
    • L的值修改为sub(L)
    • 通过调用函数xor_finder(L)xor_finder(R)来修改LR的值,分别计算从1L和从1R的 xor。
    • 初始化一个变量,比如ans并通过将值更新为final_xor(L, R)来更新ans的值。
    • 返回字符串ans作为答案。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function to subtract one
// from the binary string
string sub(string s)
{
    int n = s.size();
    for (int i = n - 1; i >= 0; i--) {
        // If the current character
        // is 0 change it to 1
        if (s[i] == '0') {
            s[i] = '1';
        }
        else {
            // If the character is 1
            // Change is to 0 and
            // terminate the loop
            s[i] = '0';
            break;
        }
    }
    // Return the answer
    return s;
}
 
// Function to add 1 in the
// binary string
string ad(string s)
{
    int n = s.size();
 
    int carry = 0;
    for (int i = n - 1; i >= 0; i--) {
        // If s[i]=='1' it
        // will change s[i] to 0
        // and carry = 1
        if (s[i] == '1') {
            carry = 1;
            s[i] = '0';
        }
        else {
            // If s[i]=='0' it
            // will change s[i] to 1
            // and carry = 0 and
            // end the loop
            carry = 0;
            s[i] = '1';
            break;
        }
    }
    // If still carry left
    // append character 1 to the
    // beginning of the string
    if (carry) {
        s = '1' + s;
    }
    return s;
}
 
// Function to find xor from 1 to n
string xor_finder(string s)
{
    int n = s.size() - 1;
 
    // Variable val stores the
    // remainder when binary string
    // is divided by 4
    int val = s[n] - '0';
    val = val + (s[n - 1] - '0') * 2;
 
    // If val == 0 the xor from
    // 1 to n will be n itself
    if (val == 0) {
        return s;
    }
    else if (val == 1) {
        // If val ==      the xor from
        // 1 to n will be 1 itself
        s = '1';
        return s;
    }
    else if (val == 2) {
        // If val == 2 the xor from
        // 1 to n will be n+1 itself
        return (ad(s));
    }
    else if (val == 3) {
        // If val == 3 the xor from
        // 1 to n will be 0 itself
        s = '0';
        return s;
    }
}
// Function to find the xor of two
// binary string
string final_xor(string L, string R)
{
    // Using loop to equalise the size
    // of string L and R
    while (L.size() != R.size()) {
        L = '0' + L;
    }
    string ans = "";
    for (int i = 0; i < L.size(); i++) {
        // If ith bit of L is 0 and
        // ith bit of R is 0
        // then xor will be 0
        if (L[i] == '0' && R[i] == '0') {
            ans += '0';
        }
        else if (L[i] == '0' && R[i] == '1'
                 || L[i] == '1' && R[i] == '0') {
            // If ith bit of L is 0 and
            // ith bit of R is 1 or
            // vice versa then xor will be 1
            ans += '1';
        }
        else {
            // If ith bit of L is 1 and
            // ith bit of R is 1
            // then xor will be 0
            ans += '0';
        }
    }
    return ans;
}
 
// Function to find xor from L to R
string xorr(string L, string R)
{
    // changing L to L - 1
    L = sub(L);
 
    // Finding xor from 1 to L - 1
    L = xor_finder(L);
 
    // Finding xor from 1 to R
    R = xor_finder(R);
 
    // Xor of 1, 2, ..., L-1 and 1, 2, ...., R
    string ans = final_xor(L, R);
 
    return ans;
}
 
// Driver Code
int main()
{
    // Given Input
    string L = "10", R = "10000";
 
    // Function Call
    cout << xorr(L, R) << endl;
    return 0;
}


Java
// Java program for above approach
class GFG{
     
// Function to subtract one
// from the binary string
public static String sub(String s)
{
    StringBuilder new_s = new StringBuilder(s);
    int n = s.length();
    for(int i = n - 1; i >= 0; i--)
    {
         
        // If the current character
        // is 0 change it to 1
        if (s.charAt(i) == '0')
        {
            new_s.setCharAt(i, '1');
        }
        else
        {
             
            // If the character is 1
            // Change is to 0 and
            // terminate the loop
            new_s.setCharAt(i, '0');
            break;
        }
    }
     
    // Return the answer
    return new_s.toString();
}
 
// Function to add 1 in the
// binary string
public static String ad(String s)
{
    int n = s.length();
    StringBuilder new_s = new StringBuilder(s);
    int carry = 0;
    for(int i = n - 1; i >= 0; i--)
    {
         
        // If s[i]=='1' it
        // will change s[i] to 0
        // and carry = 1
        if (s.charAt(i) == '1')
        {
            carry = 1;
            new_s.setCharAt(i, '0');
        }
        else
        {
             
            // If s[i]=='0' it
            // will change s[i] to 1
            // and carry = 0 and
            // end the loop
            carry = 0;
            new_s.setCharAt(i, '1');
            break;
        }
    }
     
    // If still carry left
    // append character 1 to the
    // beginning of the string
    if (carry != 0)
    {
        s = '1' + new_s.toString();
    }
    return s;
}
 
// Function to find xor from 1 to n
public static String xor_finder(String s)
{
    int n = s.length() - 1;
 
    // Variable val stores the
    // remainder when binary string
    // is divided by 4
    int val = s.charAt(n) - '0';
    val = val + (s.charAt(n - 1) - '0') * 2;
 
    // If val == 0 the xor from
    // 1 to n will be n itself
    if (val == 0)
    {
        return s;
    }
    else if (val == 1)
    {
         
        // If val == 1 the xor from
        // 1 to n will be 1 itself
        s = "1";
        return s;
    }
    else if (val == 2)
    {
         
        // If val == 2 the xor from
        // 1 to n will be n+1 itself
        return (ad(s));
    }
    else
    {
         
        // If val == 3 the xor from
        // 1 to n will be 0 itself
        s = "0";
        return s;
    }
}
 
// Function to find the xor of two
// binary string
public static String final_xor(String L, String R)
{
     
    // Using loop to equalise the size
    // of string L and R
    while (L.length() != R.length())
    {
        L = '0' + L;
    }
    String ans = "";
    for(int i = 0; i < L.length(); i++)
    {
         
        // If ith bit of L is 0 and
        // ith bit of R is 0
        // then xor will be 0
        if (L.charAt(i) == '0' && R.charAt(i) == '0')
        {
            ans += '0';
        }
        else if (L.charAt(i) == '0' && R.charAt(i) == '1' ||
                 L.charAt(i) == '1' && R.charAt(i) == '0')
        {
            // If ith bit of L is 0 and
            // ith bit of R is 1 or
            // vice versa then xor will be 1
            ans += '1';
        }
        else
        {
             
            // If ith bit of L is 1 and
            // ith bit of R is 1
            // then xor will be 0
            ans += '0';
        }
    }
    return ans;
}
 
// Function to find xor from L to R
public static String xorr(String L, String R)
{
     
    // Changing L to L - 1
    L = sub(L);
 
    // Finding xor from 1 to L - 1
    L = xor_finder(L);
 
    // Finding xor from 1 to R
    R = xor_finder(R);
 
    // Xor of 1, 2, ..., L-1 and 1, 2, ...., R
    String ans = final_xor(L, R);
 
    return ans;
}
 
// Driver code
public static void main(String[] args)
{
     
    // Given Input
    String L = "10", R = "10000";
 
    // Function Call
    System.out.println(xorr(L, R));
}
}
 
// This code is contributed by garry133


Python3
# Python program for the above approach
 
# Function to subtract one
# from the binary string
def sub(s):
   
    # Changing string into list to change
    # the characters in O(1)
    s = list(s)
    n = len(s)
    for i in range(n-1, -1, -1):
       
        # If the current character
        # is 0 change it to 1
        if (s[i] == '0'):
            s[i] = '1'
        else:
            # If the character is 1
            # Change is to 0 and
            # terminate the loop
            s[i] = '0'
            break
    # Return the answer
    # converting list to string
    s = "".join(s)
    return s
 
# Function to add 1 in the
# binary string
 
 
def ad(s):
    n = len(s)
    carry = 0
    for i in range(n-1, -1, -1):
        # If s[i]=='1' it
        # will change s[i] to 0
        # and carry = 1
        if (s[i] == '1'):
            carry = 1
            s[i] = '0'
        else:
            # If s[i]=='0' it
            # will change s[i] to 1
            # and carry = 0 and
            # end the loop
            carry = 0
            s[i] = '1'
            break
    # If still carry left
    # append character 1 to the
    # beginning of the string
    if (carry):
        s = '1' + s
    return s
 
# Function to find xor from 1 to n
 
 
def xor_finder(s):
    n = len(s) - 1
 
    # Variable val stores the
    # remainder when binary string
    # is divided by 4
    val = ord(s[n]) - 48
    val = val + (ord(s[n - 1]) - 48) * 2
 
    # If val == 0 the xor from
    # 1 to n will be n itself
    if (val == 0):
        return s
    else if (val == 1):
        # If val ==      the xor from
        # 1 to n will be 1 itself
        s = '1'
        return s
    else if (val == 2):
        # If val == 2 the xor from
        # 1 to n will be n+1 itself
        return (ad(s))
    else if (val == 3):
        # If val == 3 the xor from
        # 1 to n will be 0 itself
        s = '0'
        return s
 
# Function to find the xor of two
# binary string
 
 
def final_xor(L, R):
    # Using loop to equalise the size
    # of string L and R
    while (len(L) != len(R)):
        L = '0' + L
    ans = ""
    for i in range(len(L)):
        # If ith bit of L is 0 and
        # ith bit of R is 0
        # then xor will be 0
        if (L[i] == '0' and R[i] == '0'):
            ans += '0'
        else if (L[i] == '0' and R[i] == '1'
              or L[i] == '1' and R[i] == '0'):
            # If ith bit of L is 0 and
            # ith bit of R is 1 or
            # vice versa then xor will be 1
            ans += '1'
        else:
            # If ith bit of L is 1 and
            # ith bit of R is 1
            # then xor will be 0
            ans += '0'
    return ans
 
# Function to find xor from L to R
 
 
def xorr(L, R):
    # changing L to L - 1
    L = sub(L)
 
    # Finding xor from 1 to L - 1
    L = xor_finder(L)
 
    # Finding xor from 1 to R
    R = xor_finder(R)
 
    # Xor of 1, 2, ..., L-1 and 1, 2, ...., R
    ans = final_xor(L, R)
 
    return ans
 
# Driver Code
 
# Given Input
L = "10"
R = "10000"
 
# Function Call
print(xorr(L, R))
 
# This code is contributed by rj13to.


输出:
10001

时间复杂度: O(N) 其中 N 是字符串的长度
辅助空间: O(N)