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:
- 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).
- 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++
#include <bits/stdc++.h>
using namespace std;
#define MAX 100
#define N 5
#define M 4
int min( int a, int b, int c)
{
return min(a, min(b, c));
}
void solveQuery( int n, int m, int mat[N][M], int q,
int a[], int binary[])
{
int dp[n][m], max = 1;
for ( int i = 0; i < n; i++) {
for ( int j = 0; j < m; j++) {
if (i == 0 || j == 0)
dp[i][j] = 1;
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 };
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]]++;
}
}
for ( int i = max - 1; i >= 0; i--) {
freq0[i] += freq0[i + 1];
freq1[i] += freq1[i + 1];
}
for ( int i = 0; i < q; i++) {
if (binary[i] == 0)
cout << freq0[a[i]] << endl;
else
cout << freq1[a[i]] << endl;
}
}
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
import java.io.*;
class GFG {
static int MAX = 100 ;
static int N = 5 ;
static int M = 4 ;
static int min( int a, int b, int c)
{
return Math.min(a, Math.min(b, c));
}
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 ( int i = 0 ; i < n; i++) {
for ( int j = 0 ; j < m; j++) {
if (i == 0 || j == 0 )
dp[i][j] = 1 ;
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];
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]]++;
}
}
for ( int i = max - 1 ; i >= 0 ; i--) {
freq0[i] += freq0[i + 1 ];
freq1[i] += freq1[i + 1 ];
}
for ( int i = 0 ; i < q; i++) {
if (binary[i] == 0 )
System.out.println( freq0[a[i]]);
else
System.out.println( freq1[a[i]]);
}
}
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);
}
}
|
Python3
MAX = 100
N = 5
M = 4
def solveQuery(n, m, mat, q,
a, binary):
dp = [[ 0 for x in range (m)] for y in range (n)]
max = 1
for i in range (n):
for j in range (m):
if (i = = 0 or j = = 0 ):
dp[i][j] = 1
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
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
for i in range ( max - 1 , - 1 , - 1 ):
freq0[i] + = freq0[i + 1 ]
freq1[i] + = freq1[i + 1 ]
for i in range (q):
if (binary[i] = = 0 ):
print (freq0[a[i]])
else :
print (freq1[a[i]])
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)
|
C#
using System;
class GFG
{
static int MAX = 100;
static int min( int a,
int b,
int c)
{
return Math.Min(a, Math.Min(b, c));
}
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 ( int i = 0; i < n; i++)
{
for ( int j = 0; j < m; j++)
{
if (i == 0 || j == 0)
dp[i, j] = 1;
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];
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]]++;
}
}
for ( int i = max - 1; i >= 0; i--)
{
freq0[i] += freq0[i + 1];
freq1[i] += freq1[i + 1];
}
for ( int i = 0; i < q; i++)
{
if (binary[i] == 0)
Console.WriteLine(freq0[a[i]]);
else
Console.WriteLine(freq1[a[i]]);
}
}
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);
}
}
|
Javascript
<script>
var MAX = 100
var N = 5
var M = 4
function min(a, b, c)
{
return Math.min(a, Math.min(b, c));
}
function solveQuery(n, m, mat, q, a, binary)
{
var dp = Array.from(Array(n),()=>Array(m));
var max = 1;
for ( var i = 0; i < n; i++) {
for ( var j = 0; j < m; j++) {
if (i == 0 || j == 0)
dp[i][j] = 1;
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);
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]]++;
}
}
for ( var i = max - 1; i >= 0; i--) {
freq0[i] += freq0[i + 1];
freq1[i] += freq1[i + 1];
}
for ( var i = 0; i < q; i++) {
if (binary[i] == 0)
document.write( freq0[a[i]] + "<br>" );
else
document.write( freq1[a[i]] + "<br>" ) ;
}
}
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>
|
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
Share your thoughts in the comments
Please Login to comment...