Open In App

Maximize [length(X)/2^(XOR(X, Y))] by choosing substrings X and Y from string A and B respectively

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

Given two binary strings A and B of size N and M respectively, the task is to maximize the value of the length of (X) / 2XOR(X, Y) by choosing two substrings X and Y of equal length from the given string A and B respectively.

Examples:

Input: A = “0110”, B = “1101”
Output: 3
Explanation:
Choose the substring “110” and “110” from the string A and B respectively. The value of the expression of length(X) / 2XOR(X, Y) is 3 / 20 = 3, which is maximum among all possible combinations.

Input: A = “1111”, B = “0000”
Output: 0

Approach: The given problem can be solved by observing the expression that it needs to be maximized, therefore the denominator must be minimum, and to minimize it the value of Bitwise XOR of the substrings X and Y must be minimum i.e., zero and to make the value of Bitwise XOR as zero, the two substrings must be same. Therefore, the problem reduces to finding the Longest Common Substring of both the strings A and B. Follow the steps below to solve the problem:

  • Initialize a 2D array, say LCSuff[M + 1][N + 1] to store the lengths of the longest common suffixes of the substrings.
  • Initialize a variable, say result as 0 to store the result maximum value of the given expression.
  • Iterate over the range [0, M] using the variable i and nested iterate over the  range [0, N] using the variable j and perform the following steps:
    • If i equals 0 or j equals 0, then update the value of LCSSuff[i][j] equals 0.
    • Otherwise, if the value of A[i – 1] equals A[j – 1] then update the value of LCSSuff[i][j] as LCSSuff[i – 1][j – 1] + 1 and update the value of result as the maximum of result and LCSSuff[i][j].
    • Otherwise, update the value of LCSSuff[i][j] to 0.
  • After completing the above steps, print the value of result as the result.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the length of the
// longest common substring of the
// string X and Y
int LCSubStr(char* A, char* B, int m, int n)
{
    // LCSuff[i][j] stores the lengths
    // of the longest common suffixes
    // of substrings
    int LCSuff[m + 1][n + 1];
    int result = 0;
 
    // Iterate over strings A and B
    for (int i = 0; i <= m; i++) {
        for (int j = 0; j <= n; j++) {
 
            // If first row or column
            if (i == 0 || j == 0)
                LCSuff[i][j] = 0;
 
            // If matching is found
            else if (A[i - 1] == B[j - 1]) {
                LCSuff[i][j]
                    = LCSuff[i - 1][j - 1]
                      + 1;
                result = max(result,
                             LCSuff[i][j]);
            }
 
            // Otherwise, if matching
            // is not found
            else
                LCSuff[i][j] = 0;
        }
    }
 
    // Finally, return the resultant
    // maximum value LCS
    return result;
}
 
// Driver Code
int main()
{
    char A[] = "0110";
    char B[] = "1101";
    int M = strlen(A);
    int N = strlen(B);
 
    // Function Call
    cout << LCSubStr(A, B, M, N);
 
    return 0;
}


Java




// Java program for the above approach
class GFG{
 
// Function to find the length of the
// longest common substring of the
// string X and Y
static int lcsubtr(char a[], char b[], int length1,
                   int length2)
{
     
    // LCSuff[i][j] stores the lengths
    // of the longest common suffixes
    // of substrings
    int dp[][] = new int[length1 + 1][length2 + 1];
    int max = 0;
     
    // Iterate over strings A and B
    for(int i = 0; i <= length1; ++i)
    {
        for(int j = 0; j <= length2; ++j)
        {
             
            // If first row or column
            if (i == 0 || j == 0)
            {
                dp[i][j] = 0;
            }
             
            // If matching is found
            else if (a[i - 1] == b[j - 1])
            {
                dp[i][j] = dp[i - 1][j - 1] + 1;
                max = Math.max(dp[i][j], max);
            }
             
            // Otherwise, if matching
            // is not found
            else
            {
                dp[i][j] = 0;
            }
        }
    }
     
    // Finally, return the resultant
    // maximum value LCS
    return max;
}
 
// Driver Code
public static void main(String[] args)
{
    String m = "0110";
    String n = "1101";
    char m1[] = m.toCharArray();
    char m2[] = n.toCharArray();
     
    // Function Call
    System.out.println(lcsubtr(m1, m2, m1.length,
                                       m2.length));
}
}
 
// This code is contributed by zack_aayush


Python3




# Python 3 program for the above approach
 
# Function to find the length of the
# longest common substring of the
# string X and Y
def LCSubStr(A, B, m, n):
   
    # LCSuff[i][j] stores the lengths
    # of the longest common suffixes
    # of substrings
    LCSuff = [[0 for i in range(n+1)] for j in range(m+1)]
    result = 0
 
    # Iterate over strings A and B
    for i in range(m + 1):
        for j in range(n + 1):
           
            # If first row or column
            if (i == 0 or j == 0):
                LCSuff[i][j] = 0
 
            # If matching is found
            elif(A[i - 1] == B[j - 1]):
                LCSuff[i][j] = LCSuff[i - 1][j - 1] + 1
                result = max(result,LCSuff[i][j])
 
            # Otherwise, if matching
            # is not found
            else:
                LCSuff[i][j] = 0
 
    # Finally, return the resultant
    # maximum value LCS
    return result
 
# Driver Code
if __name__ == '__main__':
    A = "0110"
    B = "1101"
    M = len(A)
    N = len(B)
 
    # Function Call
    print(LCSubStr(A, B, M, N))
 
    # This code is contributed by SURENDRA_GANGWAR.


C#




// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
 
// Function to find the length of the
// longest common substring of the
// string X and Y
static int lcsubtr(char[] a, char[] b, int length1,
                   int length2)
{
     
    // LCSuff[i][j] stores the lengths
    // of the longest common suffixes
    // of substrings
    int[,] dp = new int[length1 + 1, length2 + 1];
    int max = 0;
     
    // Iterate over strings A and B
    for(int i = 0; i <= length1; ++i)
    {
        for(int j = 0; j <= length2; ++j)
        {
             
            // If first row or column
            if (i == 0 || j == 0)
            {
                dp[i, j] = 0;
            }
             
            // If matching is found
            else if (a[i - 1] == b[j - 1])
            {
                dp[i, j] = dp[i - 1, j - 1] + 1;
                max = Math.Max(dp[i, j], max);
            }
             
            // Otherwise, if matching
            // is not found
            else
            {
                dp[i, j] = 0;
            }
        }
    }
     
    // Finally, return the resultant
    // maximum value LCS
    return max;
}
 
// Driver Code
public static void Main()
{
    string m = "0110";
    string n = "1101";
    char[] m1 = m.ToCharArray();
    char[] m2 = n.ToCharArray();
     
    // Function Call
    Console.Write(lcsubtr(m1, m2, m1.Length,
                                       m2.Length));
}
}
 
// This code is contributed by target_2.


Javascript




<script>
 
        // JavaScript program for the above approach
 
        // Function to find the length of the
        // longest common substring of the
        // string X and Y
        function LCSubStr(A, B, m, n)
        {
         
            // LCSuff[i][j] stores the lengths
            // of the longest common suffixes
            // of substrings
            let LCSuff = Array(m + 1).fill(Array(n + 1));
            let result = 0;
 
            // Iterate over strings A and B
            for (let i = 0; i <= m; i++) {
                for (let j = 0; j <= n; j++) {
 
                    // If first row or column
                    if (i == 0 || j == 0)
                        LCSuff[i][j] = 0;
 
                    // If matching is found
                    else if (A.charAt(i - 1) == B.charAt(j - 1)) {
                        LCSuff[i][j] = LCSuff[i - 1][j - 1] + 1;
                        if (LCSuff[i][j] > result) {
                            result = LCSuff[i][j];
                        }
                    }
 
                    // Otherwise, if matching
                    // is not found
                    else
                        LCSuff[i][j] = 0;
                }
            }
            result++;
            // Finally, return the resultant
            // maximum value LCS
            return result;
        }
 
        // Driver Code
 
        let A = "0110";
        let B = "1101";
        let M = A.length;
        let N = B.length;
 
        // Function Call
        document.write(LCSubStr(A, B, M, N));
 
    // This code is contributed by Potta Lokesh
    </script>


Output

3



Time Complexity: O(M*N)
Auxiliary Space: O(M*N)

Efficient approach : Space optimization

In previous approach the current value LCSuff[i][j] is only depend upon the current and previous row values of matrix. So to optimize the space complexity we use a single 1D array to store the computations.

Implementation steps:

  • Create a 1D vector LCSuff of size n+1.
  • Set a base case by initializing the values of LCSuff.
  • Now iterate over subproblems by the help of nested loop and get the current value from previous computations.
  • Now Create a temporary variables prev used to store previous computations and temp for current value.
  • After every iteration assign the value of temp to prev for further iteration.
  • Initialize a variable result to store the final answer and update it by iterating through the LCSuff.
  • At last return and print the final answer stored in result.

Implementation: 

C++




// C++ code for above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the length of the
// longest common substring of the
// string X and Y
int LCSubStr(char* A, char* B, int m, int n)
{  
     // LCSuff[] stores the lengths
    // of the longest common suffixes
    // of substrings
    int LCSuff[n + 1];
    int result = 0;
 
    // Iterate over strings A and B
    for (int i = 0; i <= m; i++) {
         
        // previous element
        int prev = 0;
        for (int j = 0; j <= n; j++) {
            int temp = LCSuff[j];
             
             // If first row or column
            if (i == 0 || j == 0)
                LCSuff[j] = 0;
             // If matching is found
            else if (A[i - 1] == B[j - 1]) {
                LCSuff[j] = prev + 1;
                result = max(result, LCSuff[j]);
            }
            // Otherwise, if matching
            // is not found
            else
                LCSuff[j] = 0;
            prev = temp;
        }
    }
     
    // Finally, return the resultant
    // maximum value LCS
    return result;
}
 
// Driver code
int main()
{
    char A[] = "0110";
    char B[] = "1101";
    int M = strlen(A);
    int N = strlen(B);
     
    // function call
    cout << LCSubStr(A, B, M, N);
 
    return 0;
}
 
// --- by bhardwajji


Java




// Java code for above approach
 
import java.util.*;
 
public class Main
{
 
  // Function to find the length of the
  // longest common substring of the
  // string X and Y
  public static int LCSubStr(char[] A, char[] B, int m, int n)
  {
 
    // LCSuff[] stores the lengths
    // of the longest common suffixes
    // of substrings
    int[] LCSuff = new int[n + 1];
    int result = 0;
    // Iterate over strings A and B
    for (int i = 0; i <= m; i++) {
      // previous element
      int prev = 0;
      for (int j = 0; j <= n; j++) {
        int temp = LCSuff[j];
 
        // If first row or column
        if (i == 0 || j == 0)
          LCSuff[j] = 0;
        // If matching is found
        else if (A[i - 1] == B[j - 1]) {
          LCSuff[j] = prev + 1;
          result = Math.max(result, LCSuff[j]);
        }
        // Otherwise, if matching
        // is not found
        else
          LCSuff[j] = 0;
        prev = temp;
      }
    }
 
    // Finally, return the resultant
    // maximum value LCS
    return result;
  }
 
  // Driver code
  public static void main(String[] args) {
    char[] A = "0110".toCharArray();
    char[] B = "1101".toCharArray();
    int M = A.length;
    int N = B.length;
 
    // function call
    System.out.println(LCSubStr(A, B, M, N));
  }
}


Python




def LCSubStr(A, B, m, n):
    # LCSuff[] stores the lengths
    # of the longest common suffixes
    # of substrings
    LCSuff = [0] * (n + 1)
    result = 0
 
    # Iterate over strings A and B
    for i in range(m+1):
        # previous element
        prev = 0
        for j in range(n+1):
            temp = LCSuff[j]
             
            # If first row or column
            if i == 0 or j == 0:
                LCSuff[j] = 0
            # If matching is found
            elif A[i - 1] == B[j - 1]:
                LCSuff[j] = prev + 1
                result = max(result, LCSuff[j])
            # Otherwise, if matching
            # is not found
            else:
                LCSuff[j] = 0
            prev = temp
     
    # Finally, return the resultant
    # maximum value LCS
    return result
 
# Driver code
A = "0110"
B = "1101"
M = len(A)
N = len(B)
 
# function call
print(LCSubStr(A, B, M, N))


C#




using System;
 
public class GFG
{
    // Function to find the length of the
    // longest common substring of the
    // string X and Y
    public static int LCSubStr(char[] A, char[] B, int m, int n)
    {
        // LCSuff[] stores the lengths
        // of the longest common suffixes
        // of substrings
        int[] LCSuff = new int[n + 1];
        int result = 0;
 
        // Iterate over strings A and B
        for (int i = 0; i <= m; i++)
        {
            // previous element
            int prev = 0;
            for (int j = 0; j <= n; j++)
            {
                int temp = LCSuff[j];
 
                // If first row or column
                if (i == 0 || j == 0)
                    LCSuff[j] = 0;
                // If matching is found
                else if (A[i - 1] == B[j - 1])
                {
                    LCSuff[j] = prev + 1;
                    result = Math.Max(result, LCSuff[j]);
                }
                // Otherwise, if matching
                // is not found
                else
                    LCSuff[j] = 0;
 
                prev = temp;
            }
        }
 
        // Finally, return the resultant
        // maximum value LCS
        return result;
    }
 
    // Driver code
    public static void Main(string[] args)
    {
        char[] A = "0110".ToCharArray();
        char[] B = "1101".ToCharArray();
        int M = A.Length;
        int N = B.Length;
 
        // function call
        Console.WriteLine(LCSubStr(A, B, M, N));
    }
}


Javascript




function LCSubStr(A, B, m, n) {
    // LCSuff[] stores the lengths
    // of the longest common suffixes
    // of substrings
    const LCSuff = new Array(n + 1).fill(0);
    let result = 0;
 
    // Iterate over strings A and B
    for (let i = 0; i <= m; i++) {
        // previous element
        let prev = 0;
        for (let j = 0; j <= n; j++) {
            let temp = LCSuff[j];
 
            // If first row or column
            if (i === 0 || j === 0)
                LCSuff[j] = 0;
            // If matching is found
            else if (A[i - 1] === B[j - 1]) {
                LCSuff[j] = prev + 1;
                result = Math.max(result, LCSuff[j]);
            }
            // Otherwise, if matching
            // is not found
            else
                LCSuff[j] = 0;
            prev = temp;
        }
    }
 
    // Finally, return the resultant
    // maximum value LCS
    return result;
}
 
// Driver code
const A = "0110";
const B = "1101";
const M = A.length;
const N = B.length;
 
// Function call
console.log(LCSubStr(A, B, M, N));


Output: 

3

 

Time Complexity: O(M*N)
Auxiliary Space: O(N)

 



Last Updated : 19 Sep, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads