Queries on number of Binary sub-matrices of Given size

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 oth 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 oth 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.
Output:

4
1

Time Complexity of the above algorithm is O(n * m)




Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.




Article Tags :
Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.

Recommended Posts:



3 Average Difficulty : 3/5.0
Based on 2 vote(s)