Given two arrays A[] and B[], and an integer K, the task is to find the number of ways to select two subarrays of the same size, one from A and the other one from B such that the subarrays have at least K equal pairs of elements. (i.e. the number of pairs (A[i], B[j]) in the two selected subarrays such that A[i] = B[j] >= K).
Examples:Â
Input: A[] = {1, 2}, B[] = {1, 2, 3}, K = 1
Output: 4Â
The ways to select two subarrays are:
- [1], [1]
- [2], [2]
- [1, 2], [1, 2]
- [1, 2], [2, 3]
Input: A[] = {3, 2, 5, 21, 15, 2, 6}, B[] = {2, 1, 4, 3, 6, 7, 9}, K = 2
Output: 7Â
Approach:Â Â
- Instead of dealing with the two arrays separately, let’s combine them in form of a binary matrix such that:
mat[i][j] = 0, if A[i] != B[j]
= 1, if A[i] = B[j]
- Now if we consider any submatrix of this matrix, say of size P × Q, it’s basically a combination of a subarray from A of size P and a subarray from B of size Q. Since we only want to check for equal-sized subarrays, we will consider only square submatrices.
- Let’s consider a square submatrix with top left corner as (i, j) and bottom right corner as (i + size,, j + size). This is equivalent to considering subarrays A[i: i + size] and B[j: j + size]. It can be observed that if these two subarrays will have x pairs of equal elements then the submatrix will have x 1’s in it.
- So traverse over all the elements of the matrix (i, j) and consider them to be the bottom right corner of the square. Now, one way is to traverse all the possible sizes of submatrix and find the sizes which have sum >= k, but this will be less efficient. It can be observed that say if a S x S submatrix with (i, j) as bottom right corner has sum >= k, then all square submatrices with size >= S and (i, j) as bottom right corner will follow the property.
- So instead of iterating for all sizes at each (i, j), we will just apply binary search over the size of the square submatrix and find the smallest size S such that it has sum >= K, and then simply add the matrices with greater side lengths.Â
This article can be referred to see how submatrix sums are evaluated in constant time using 2D prefix sums.
Below is the implementation of the above approach:
C++
// C++ implementation to count the // number of ways to select equal// sized subarrays such that they// have atleast K common elementsÂ
#include <bits/stdc++.h>Â
using namespace std;Â
// 2D prefix sum for submatrix // sum query for matrixint prefix_2D[2005][2005];Â
// Function to find the prefix sum// of the matrix from i and jint subMatrixSum(int i, int j, int len){Â Â Â Â return prefix_2D[i][j] - Â Â Â Â Â Â Â Â Â Â Â prefix_2D[i][j - len] - Â Â Â Â Â Â Â Â Â Â Â prefix_2D[i - len][j] + Â Â Â Â Â Â Â Â Â Â Â prefix_2D[i - len][j - len];}Â
// Function to count the number of ways// to select equal sized subarrays such// that they have atleast K common elementsint numberOfWays(int a[], int b[], int n, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int m, int k){Â
    // Combining the two arrays    for (int i = 1; i <= n; i++) {        for (int j = 1; j <= m; j++) {            if (a[i - 1] == b[j - 1])                prefix_2D[i][j] = 1;Â
            else                prefix_2D[i][j] = 0;        }    }Â
    // Calculating the 2D prefix sum    for (int i = 1; i <= n; i++) {        for (int j = 1; j <= m; j++) {            prefix_2D[i][j] += prefix_2D[i][j - 1];        }    }Â
    for (int i = 1; i <= n; i++) {        for (int j = 1; j <= m; j++) {            prefix_2D[i][j] += prefix_2D[i - 1][j];        }    }Â
    int answer = 0;Â
    // iterating through all     // the elements of matrix    // and considering them to     // be the bottom right    for (int i = 1; i <= n; i++) {        for (int j = 1; j <= m; j++) {                         // applying binary search             // over side length            int low = 1;            int high = min(i, j);Â
            while (low < high) {                int mid = (low + high) >> 1;Â
                // if sum of this submatrix >=k then                // new search space will be [low, mid]                if (subMatrixSum(i, j, mid) >= k) {                    high = mid;                }                // else new search space                 // will be [mid+1, high]                else {                    low = mid + 1;                }            }Â
            // Adding the total submatrices            if (subMatrixSum(i, j, low) >= k) {                answer += (min(i, j) - low + 1);            }        }    }    return answer;}Â
// Driver Codeint main(){Â Â Â Â int N = 2, M = 3;Â Â Â Â int A[N] = { 1, 2 };Â Â Â Â int B[M] = { 1, 2, 3 };Â
    int K = 1;Â
    cout << numberOfWays(A, B, N, M, K);    return 0;} |
Java
// Java implementation to count the // number of ways to select equal// sized subarrays such that they// have atleast K common elementsclass GFG{Â
// 2D prefix sum for submatrix // sum query for matrixstatic int [][]prefix_2D = new int[2005][2005];Â
// Function to find the prefix sum// of the matrix from i and jstatic int subMatrixSum(int i, int j, int len){Â Â Â Â return prefix_2D[i][j] - Â Â Â Â Â Â Â Â Â Â Â prefix_2D[i][j - len] - Â Â Â Â Â Â Â Â Â Â Â prefix_2D[i - len][j] + Â Â Â Â Â Â Â Â Â Â Â prefix_2D[i - len][j - len];}Â
// Function to count the number of ways// to select equal sized subarrays such// that they have atleast K common elementsstatic int numberOfWays(int a[], int b[], int n,                         int m, int k){         // Combining the two arrays    for(int i = 1; i <= n; i++)     {       for(int j = 1; j <= m; j++)       {          if (a[i - 1] == b[j - 1])              prefix_2D[i][j] = 1;          else              prefix_2D[i][j] = 0;       }    }Â
    // Calculating the 2D prefix sum    for(int i = 1; i <= n; i++)    {       for(int j = 1; j <= m; j++)        {          prefix_2D[i][j] += prefix_2D[i][j - 1];       }    }Â
    for(int i = 1; i <= n; i++)     {       for(int j = 1; j <= m; j++)        {          prefix_2D[i][j] += prefix_2D[i - 1][j];       }    }Â
    int answer = 0;Â
    // Iterating through all     // the elements of matrix    // and considering them to     // be the bottom right    for(int i = 1; i <= n; i++)    {       for(int j = 1; j <= m; j++)       {                     // Applying binary search           // over side length          int low = 1;          int high = Math.min(i, j);                     while (low < high)          {              int mid = (low + high) >> 1;                             // If sum of this submatrix >=k then              // new search space will be [low, mid]              if (subMatrixSum(i, j, mid) >= k)              {                  high = mid;              }                             // Else new search space               // will be [mid+1, high]              else              {                  low = mid + 1;              }          }                     // Adding the total submatrices          if (subMatrixSum(i, j, low) >= k)          {              answer += (Math.min(i, j) - low + 1);          }       }    }    return answer;}Â
// Driver Codepublic static void main(String[] args){Â Â Â Â int N = 2, M = 3;Â Â Â Â int A[] = { 1, 2 };Â Â Â Â int B[] = { 1, 2, 3 };Â
    int K = 1;Â
    System.out.print(numberOfWays(A, B, N, M, K));}}Â
// This code is contributed by Princi Singh |
Python3
# Python3 implementation to count the # number of ways to select equal# sized subarrays such that they# have atleast K common elementÂ
# 2D prefix sum for submatrix # sum query for matrixprefix_2D = [[0 for x in range (2005)]Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â for y in range (2005)]Â
# Function to find the prefix sum# of the matrix from i and jdef subMatrixSum(i, j, length):Â
    return (prefix_2D[i][j] -            prefix_2D[i][j - length] -            prefix_2D[i - length][j] +            prefix_2D[i - length][j - length])Â
# Function to count the number of ways# to select equal sized subarrays such# that they have atleast K common elementsdef numberOfWays(a, b, n, m, k):Â
    # Combining the two arrays    for i in range (1, n + 1):        for j in range (1, m + 1):            if (a[i - 1] == b[j - 1]):                prefix_2D[i][j] = 1            else:                prefix_2D[i][j] = 0           # Calculating the 2D prefix sum    for i in range (1, n + 1):        for j in range (1, m + 1):            prefix_2D[i][j] += prefix_2D[i][j - 1]            for i in range (1, n + 1):        for j in range (1, m + 1):            prefix_2D[i][j] += prefix_2D[i - 1][j]    answer = 0Â
    # iterating through all     # the elements of matrix    # and considering them to     # be the bottom right    for i in range (1, n +1):        for j in range (1, m + 1):                         # applying binary search             # over side length            low = 1            high = min(i, j)Â
            while (low < high):                mid = (low + high) >> 1Â
                # if sum of this submatrix >=k then                # new search space will be [low, mid]                if (subMatrixSum(i, j, mid) >= k):                    high = mid                                 # else new search space                 # will be [mid+1, high]                else:                    low = mid + 1Â
            # Adding the total submatrices            if (subMatrixSum(i, j, low) >= k):                answer += (min(i, j) - low + 1)              return answerÂ
# Driver Codeif __name__ == "__main__":Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â N = 2Â Â Â Â M = 3Â Â Â Â A = [1, 2]Â Â Â Â B = [1, 2, 3]Â Â Â Â K = 1Â Â Â Â print (numberOfWays(A, B, N, M, K))Â
# This code is contributed by Chitranayal |
C#
// C# implementation to count the // number of ways to select equal// sized subarrays such that they// have atleast K common elementsusing System;Â
class GFG{Â
// 2D prefix sum for submatrix // sum query for matrixstatic int [,]prefix_2D = new int[2005, 2005];Â
// Function to find the prefix sum// of the matrix from i and jstatic int subMatrixSum(int i, int j, int len){Â Â Â Â return prefix_2D[i, j] - Â Â Â Â Â Â Â Â Â Â Â prefix_2D[i, j - len] - Â Â Â Â Â Â Â Â Â Â Â prefix_2D[i - len, j] + Â Â Â Â Â Â Â Â Â Â Â prefix_2D[i - len, j - len];}Â
// Function to count the number of ways// to select equal sized subarrays such// that they have atleast K common elementsstatic int numberOfWays(int []a, int []b, int n,                         int m, int k){         // Combining the two arrays    for(int i = 1; i <= n; i++)     {       for(int j = 1; j <= m; j++)       {          if (a[i - 1] == b[j - 1])              prefix_2D[i, j] = 1;          else              prefix_2D[i, j] = 0;       }    }Â
    // Calculating the 2D prefix sum    for(int i = 1; i <= n; i++)    {       for(int j = 1; j <= m; j++)       {          prefix_2D[i, j] += prefix_2D[i, j - 1];                   }    }Â
    for(int i = 1; i <= n; i++)     {       for(int j = 1; j <= m; j++)        {          prefix_2D[i, j] += prefix_2D[i - 1, j];       }    }Â
    int answer = 0;Â
    // Iterating through all     // the elements of matrix    // and considering them to     // be the bottom right    for(int i = 1; i <= n; i++)    {       for(int j = 1; j <= m; j++)       {                      // Applying binary search           // over side length          int low = 1;          int high = Math.Min(i, j);          while (low < high)          {              int mid = (low + high) >> 1;                             // If sum of this submatrix >=k then              // new search space will be [low, mid]              if (subMatrixSum(i, j, mid) >= k)              {                  high = mid;              }                             // Else new search space               // will be [mid+1, high]              else              {                  low = mid + 1;              }          }                     // Adding the total submatrices          if (subMatrixSum(i, j, low) >= k)          {              answer += (Math.Min(i, j) - low + 1);          }       }    }    return answer;}Â
// Driver Codepublic static void Main(String[] args){Â Â Â Â int N = 2, M = 3;Â Â Â Â int []A = { 1, 2 };Â Â Â Â int []B = { 1, 2, 3 };Â
    int K = 1;Â
    Console.Write(numberOfWays(A, B, N, M, K));}}Â
// This code is contributed by Princi Singh |
Javascript
<script>// javascript implementation to count the // number of ways to select equal// sized subarrays such that they// have atleast K common elements   // 2D prefix sum for submatrix    // sum query for matrix    var prefix_2D = Array(2005);Â
    // Function to find the prefix sum    // of the matrix from i and j    function subMatrixSum(i , j , len) {        return prefix_2D[i][j] - prefix_2D[i][j - len] - prefix_2D[i - len][j] + prefix_2D[i - len][j - len];    }Â
    // Function to count the number of ways    // to select equal sized subarrays such    // that they have atleast K common elements    function numberOfWays(a , b , n , m , k) {Â
        // Combining the two arrays        for (i = 1; i <= n; i++) {            for (j = 1; j <= m; j++) {                if (a[i - 1] == b[j - 1])                    prefix_2D[i][j] = 1;                else                    prefix_2D[i][j] = 0;            }        }Â
        // Calculating the 2D prefix sum        for (i = 1; i <= n; i++) {            for (j = 1; j <= m; j++) {                prefix_2D[i][j] += prefix_2D[i][j - 1];            }        }Â
        for (i = 1; i <= n; i++) {            for (j = 1; j <= m; j++) {                prefix_2D[i][j] += prefix_2D[i - 1][j];            }        }Â
        var answer = 0;Â
        // Iterating through all        // the elements of matrix        // and considering them to        // be the bottom right        for (i = 1; i <= n; i++) {            for (j = 1; j <= m; j++) {Â
                // Applying binary search                // over side length                var low = 1;                var high = Math.min(i, j);Â
                while (low < high) {                    var mid = (low + high) >> 1;Â
                    // If sum of this submatrix >=k then                    // new search space will be [low, mid]                    if (subMatrixSum(i, j, mid) >= k) {                        high = mid;                    }Â
                    // Else new search space                    // will be [mid+1, high]                    else {                        low = mid + 1;                    }                }Â
                // Adding the total submatrices                if (subMatrixSum(i, j, low) >= k) {                    answer += (Math.min(i, j) - low + 1);                }            }        }        return answer;    }Â
    // Driver Code             var N = 2, M = 3;        var A = [ 1, 2 ];        var B = [ 1, 2, 3 ];        for(i = 0;i<205;i++)        prefix_2D[i] = Array(205).fill(0);        var K = 1;Â
        document.write(numberOfWays(A, B, N, M, K));Â
// This code contributed by Rajput-Ji </script> |
4
Â
Time Complexity: O(N * M * log(max(N, M)))
Auxiliary Space: O(MAX2) where MAX is the defined constant
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!
