Open In App

Queries on number of Binary sub-matrices of Given size

Improve
Improve
Like Article
Like
Save
Share
Report

Given a Binary Matrix of size N X M, the task is to answer Q queries of the following type;

Query(a, b): Find the number of sub matrices of size a X a with each of its element consisting of the Binary Number b.

We basically need to find submatrices of given sizes with all 1s or all 0s.

Examples:  

Input : N = 5, M = 4
        m[][] = { { 0, 0, 1, 1 },
                  { 0, 0, 1, 0 },
                  { 0, 1, 1, 1 },
                  { 1, 1, 1, 1 },
                  { 0, 1, 1, 1 }
                }
        Q = 2
        Query 1 : a = 2, b = 1
        Query 2 : a = 2, b = 0 
Output : 4 1

Explanation:
For Query 1,
0011  0011  0011  0011
0010  0010  0010  0010
0111  0111  0111  0111
1111  1111  1111  1111
0111  0111  0111  0111

For Query 2,
0011
0010
0111
1111
0111

Input : N = 5, M = 4
        m[][] = { { 0, 0, 1, 1 },
                  { 0, 0, 1, 0 },
                  { 0, 1, 1, 1 },
                  { 1, 1, 1, 1 },
                  { 0, 1, 1, 1 }
                }

        Q = 1
        Query 1 : a = 3, b = 1
Output : 1

The idea is to use Dynamic Programming to solve the problem. First declare a 2D array dp[][], where value at dp[i][j] (say K) indicates the size of the largest square sub-matrix (K X K) that can be formed whose all elements are equal to m[i][j] and (i, j) is the last element (south-east) of the sub matrix. 

Now, dp[i][j] can be defined as: 

  1. If i = 0 OR j = 0 In this Case, dp[i][j] = 1, because only 1 X 1 is the only square matrix that can be formed at 0th row or 0th column whose all elements are equal to m[i][j] and the last element is (i, 0) or (0, j).
  2. If m[i][j] = m[i-1][j] = m[i][j-1] = m[i-1][j-1] dp[i][j] = min(dp[i][j-1], dp[i-1][j], dp[i-1][j-1]) + 1, if the binary number at m[i][j] is equal to the binary number at m[i-1][j], m[i-1][j-1] and m[i][j-1]. Because if the current binary number is equal to all the three binary numbers it will form a 2 X 2 square sub-matrix where all the elements are equal. Also, it will contribute 1 more row and column to the square matrix with all equal element at position m[i-1][j], m[i-1][j-1] and m[i][j-1].
    dp[i][j] = 1, if above conditions do not meet because a single cell will always contribute a 1 X 1 sub matrix.

Now, traverse the 2D dp[][] array and calculate the frequency (freq0[] for the element 0, freq1[] for the element 1) of all the distinct values i.e distinct sizes of square sub-matrix for both 0s and 1s. 

Observe, that to count the square sub-matrix of size Y X Y, then Y+1 X Y+1 will also contribute 1 count. Suppose we need to count 2 X 2 matrix and dp[][]=  

...22
...23

Here, the frequency of two is 3 but observe element where dp[i][j] = 3 is also contributing a 2 X 2 square sub-matrix. 
So, find the cumulative sum of the frequency for both freq0[] and freq1[].

Below is the implementation of this approach:  

C++




// CPP Program to answer queries on number of
// submatrix of given size
#include <bits/stdc++.h>
using namespace std;
 
#define MAX 100
#define N 5
#define M 4
 
// Return the minimum of three numbers
int min(int a, int b, int c)
{
    return min(a, min(b, c));
}
 
// Solve each query on matrix
void solveQuery(int n, int m, int mat[N][M], int q,
                             int a[], int binary[])
{
    int dp[n][m], max = 1;
 
    // For each of the cell.
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
 
            // finding submatrix size of both row
            // and column.
            if (i == 0 || j == 0)
                dp[i][j] = 1;
 
            // intermediate cells.
            else if ((mat[i][j] == mat[i - 1][j]) &&
                     (mat[i][j] == mat[i][j - 1]) &&
                     (mat[i][j] == mat[i - 1][j - 1])) {
 
                dp[i][j] = min(dp[i - 1][j], dp[i - 1][j - 1],
                               dp[i][j - 1])
                           + 1;
 
                if (max < dp[i][j])
                    max = dp[i][j];
            }
 
            else
                dp[i][j] = 1;
        }
    }
 
    int freq0[MAX] = { 0 }, freq1[MAX] = { 0 };
 
    // Find frequency of each distinct size
    // for 0s and 1s.
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (mat[i][j] == 0)
                freq0[dp[i][j]]++;
            else
                freq1[dp[i][j]]++;
        }
    }
 
    // Find the Cumulative Sum.
    for (int i = max - 1; i >= 0; i--) {
        freq0[i] += freq0[i + 1];
        freq1[i] += freq1[i + 1];
    }
 
    // Output the answer for each query
    for (int i = 0; i < q; i++) {
        if (binary[i] == 0)
            cout << freq0[a[i]] << endl;
        else
            cout << freq1[a[i]] << endl;
    }
}
 
// Driver Program
int main()
{
    int n = 5, m = 4;
    int mat[N][M] = {
        { 0, 0, 1, 1 },
        { 0, 0, 1, 0 },
        { 0, 1, 1, 1 },
        { 1, 1, 1, 1 },
        { 0, 1, 1, 1 }
    };
    int q = 2;
    int a[] = { 2, 2 };
    int binary[] = { 1, 0 };
 
    solveQuery(n, m, mat, q, a, binary);
 
    return 0;
}


Java




// Java Program to answer queries on number of
// submatrix of given size
import java.io.*;
 
class GFG {
 
    static int MAX = 100;
    static int N = 5;
    static int M = 4;
     
    // Return the minimum of three numbers
    static int min(int a, int b, int c)
    {
        return Math.min(a, Math.min(b, c));
    }
     
    // Solve each query on matrix
    static void solveQuery(int n, int m, int mat[][],
                        int q, int a[], int binary[])
    {
        int dp[][] = new int[n][m];
        int max = 1;
     
        // For each of the cell.
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
     
                // finding submatrix size of both row
                // and column.
                if (i == 0 || j == 0)
                    dp[i][j] = 1;
     
                // intermediate cells.
                else if ((mat[i][j] == mat[i - 1][j])
                      && (mat[i][j] == mat[i][j - 1])
                 && (mat[i][j] == mat[i - 1][j - 1]))
                 {
     
                    dp[i][j] = min(dp[i - 1][j],
                               dp[i - 1][j - 1],
                                dp[i][j - 1]) + 1;
     
                    if (max < dp[i][j])
                        max = dp[i][j];
                }
     
                else
                    dp[i][j] = 1;
            }
        }
     
        int freq0[] = new int[MAX];
        int freq1[] = new int[MAX];
     
        // Find frequency of each distinct size
        // for 0s and 1s.
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (mat[i][j] == 0)
                    freq0[dp[i][j]]++;
                else
                    freq1[dp[i][j]]++;
            }
        }
     
        // Find the Cumulative Sum.
        for (int i = max - 1; i >= 0; i--) {
            freq0[i] += freq0[i + 1];
            freq1[i] += freq1[i + 1];
        }
     
        // Output the answer for each query
        for (int i = 0; i < q; i++) {
            if (binary[i] == 0)
                System.out.println( freq0[a[i]]);
            else
                System.out.println( freq1[a[i]]);
        }
    }
     
    // Driver Program
 
    public static void main (String[] args)
    {
        int n = 5, m = 4;
        int mat[][] = { { 0, 0, 1, 1 },
                        { 0, 0, 1, 0 },
                        { 0, 1, 1, 1 },
                        { 1, 1, 1, 1 },
                        { 0, 1, 1, 1 } };
        int q = 2;
        int a[] = { 2, 2 };
        int binary[] = { 1, 0 };
     
        solveQuery(n, m, mat, q, a, binary);
    }
}
 
// This code is contributed by anuj_67.


Python3




# Python 3 Program to answer queries on number of
# submatrix of given size
MAX = 100
N = 5
M = 4
 
# Solve each query on matrix
def solveQuery(n, m, mat, q,
               a, binary):
 
    dp = [[0 for x in range(m)]for y in range(n)]
    max = 1
 
    # For each of the cell.
    for i in range(n):
        for j in range(m):
 
            # finding submatrix size of both row
            # and column.
            if (i == 0 or j == 0):
                dp[i][j] = 1
 
            # intermediate cells.
            elif ((mat[i][j] == mat[i - 1][j]) and
                  (mat[i][j] == mat[i][j - 1]) and
                  (mat[i][j] == mat[i - 1][j - 1])):
 
                dp[i][j] = (min(dp[i - 1][j], min(dp[i - 1][j - 1],
                                                  dp[i][j - 1])) + 1)
 
                if (max < dp[i][j]):
                    max = dp[i][j]
 
            else:
                dp[i][j] = 1
 
    freq0 = [0] * MAX
    freq1 = [0] * MAX
 
    # Find frequency of each distinct size
    # for 0s and 1s.
    for i in range(n):
        for j in range(m):
            if (mat[i][j] == 0):
                freq0[dp[i][j]] += 1
            else:
                freq1[dp[i][j]] += 1
 
    # Find the Cumulative Sum.
    for i in range(max - 1, -1, -1):
        freq0[i] += freq0[i + 1]
        freq1[i] += freq1[i + 1]
 
    # Output the answer for each query
    for i in range(q):
        if (binary[i] == 0):
            print(freq0[a[i]])
        else:
            print(freq1[a[i]])
 
 
# Driver Program
if __name__ == "__main__":
 
    n = 5
    m = 4
    mat = [
        [0, 0, 1, 1],
        [0, 0, 1, 0],
        [0, 1, 1, 1],
        [1, 1, 1, 1],
        [0, 1, 1, 1]
    ]
    q = 2
    a = [2, 2]
    binary = [1, 0]
 
    solveQuery(n, m, mat, q, a, binary)
 
    # This code is contributed by ukasp.


C#




// C# Program to answer
// queries on number of
// submatrix of given size
using System;
 
class GFG
{
    static int MAX = 100;
    // static int N = 5;
    // static int M = 4;
     
    // Return the minimum
    // of three numbers
    static int min(int a,
                   int b,
                   int c)
    {
        return Math.Min(a, Math.Min(b, c));
    }
     
    // Solve each query on matrix
    static void solveQuery(int n, int m,
                           int [,]mat, int q,
                           int []a, int []binary)
    {
        int [,]dp = new int[n, m];
        int max = 1;
     
        // For each of the cell.
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
     
                // finding submatrix size
                // of both row and column.
                if (i == 0 || j == 0)
                    dp[i, j] = 1;
     
                // intermediate cells.
                else if ((mat[i, j] == mat[i - 1, j]) &&
                         (mat[i, j] == mat[i, j - 1]) &&
                         (mat[i, j] == mat[i - 1, j - 1]))
                {
     
                    dp[i, j] = min(dp[i - 1, j],
                                   dp[i - 1, j - 1],
                                   dp[i, j - 1]) + 1;
     
                    if (max < dp[i, j])
                        max = dp[i, j];
                }
     
                else
                    dp[i, j] = 1;
            }
        }
     
        int []freq0 = new int[MAX];
        int []freq1 = new int[MAX];
     
        // Find frequency of each
        // distinct size for 0s and 1s.
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                if (mat[i, j] == 0)
                    freq0[dp[i, j]]++;
                else
                    freq1[dp[i, j]]++;
            }
        }
     
        // Find the Cumulative Sum.
        for (int i = max - 1; i >= 0; i--)
        {
            freq0[i] += freq0[i + 1];
            freq1[i] += freq1[i + 1];
        }
     
        // Output the answer
        // for each query
        for (int i = 0; i < q; i++)
        {
            if (binary[i] == 0)
                Console.WriteLine(freq0[a[i]]);
            else
                Console.WriteLine(freq1[a[i]]);
        }
    }
     
    // Driver Code
    public static void Main ()
    {
        int n = 5, m = 4;
        int [,]mat = {{0, 0, 1, 1},
                      {0, 0, 1, 0},
                      {0, 1, 1, 1},
                      {1, 1, 1, 1},
                      {0, 1, 1, 1}};
        int q = 2;
        int []a = {2, 2};
        int []binary = {1, 0};
     
        solveQuery(n, m, mat,
                   q, a, binary);
    }
}
 
// This code is contributed by anuj_67.


Javascript




<script>
 
// Javascript Program to answer queries on number of
// submatrix of given size
 
var MAX = 100
var N = 5
var M = 4
 
// Return the minimum of three numbers
function min(a, b, c)
{
    return Math.min(a, Math.min(b, c));
}
 
// Solve each query on matrix
function solveQuery(n, m, mat, q, a, binary)
{
    var dp = Array.from(Array(n),()=>Array(m));
    var max = 1;
 
    // For each of the cell.
    for (var i = 0; i < n; i++) {
        for (var j = 0; j < m; j++) {
 
            // finding submatrix size of both row
            // and column.
            if (i == 0 || j == 0)
                dp[i][j] = 1;
 
            // intermediate cells.
            else if ((mat[i][j] == mat[i - 1][j]) &&
                     (mat[i][j] == mat[i][j - 1]) &&
                     (mat[i][j] == mat[i - 1][j - 1])) {
 
                dp[i][j] = Math.min(dp[i - 1][j], dp[i - 1][j - 1],
                               dp[i][j - 1])
                           + 1;
 
                if (max < dp[i][j])
                    max = dp[i][j];
            }
 
            else
                dp[i][j] = 1;
        }
    }
 
    var freq0 = Array(MAX).fill(0);
    var freq1 = Array(MAX).fill(0);
 
    // Find frequency of each distinct size
    // for 0s and 1s.
    for (var i = 0; i < n; i++) {
        for (var j = 0; j < m; j++) {
            if (mat[i][j] == 0)
                freq0[dp[i][j]]++;
            else
                freq1[dp[i][j]]++;
        }
    }
 
    // Find the Cumulative Sum.
    for (var i = max - 1; i >= 0; i--) {
        freq0[i] += freq0[i + 1];
        freq1[i] += freq1[i + 1];
    }
 
    // Output the answer for each query
    for (var i = 0; i < q; i++) {
        if (binary[i] == 0)
            document.write( freq0[a[i]] + "<br>");
        else
            document.write( freq1[a[i]] + "<br>") ;
    }
}
 
// Driver Program
var n = 5, m = 4;
var mat = [
    [ 0, 0, 1, 1 ],
    [ 0, 0, 1, 0 ],
    [ 0, 1, 1, 1 ],
    [ 1, 1, 1, 1 ],
    [ 0, 1, 1, 1 ]
];
var q = 2;
var a = [ 2, 2 ];
var binary = [ 1, 0 ];
solveQuery(n, m, mat, q, a, binary);
 
</script>


Output

4
1

Time Complexity: O(n * m), where n and m are the numbers of rows and columns respectively.
Auxiliary Space: O(n * m + MAX)



Last Updated : 05 Dec, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads