Related Articles
Queries on number of Binary sub-matrices of Given size
• Difficulty Level : Medium
• Last Updated : 05 May, 2021

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 ``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.`

## 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 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)``                ``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

 ``
Output:
```4
1```

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

My Personal Notes arrow_drop_up