判断矩阵中是否存在所有元素相同的子矩阵

例题链接

新大陆

思路

首先预处理,设第 $i$ 行第 $j$ 列的元素为$a_{ij}$ ,定义数组 $cnt_{ij}$ 统计第 $i$ 行以 $a_{ij}$ 开头且后面元素均等于 $a_{ij}$ 的子数组的最大长度。

一个子矩阵有 $h\times w$ 和 $w\times h$ 两种形式,以 $h\times w$ 为例:

从上至下,从左到右遍历 $a_{ij}$ ,定义数组 $b_{ij}$ 统计以 $a_{ij}$ 为左下角且长大于等于 $h$ 的子矩阵的最大行数,具体计算方法为:若 $cnt[i][j]\ge h$ ,则 $b[i][j]=1$ ,若又有 $a[i][j]=a[i-1][j]$ ,则 $b[i][j]+=b[i-1][j]$。当 $b[i][j]=w$ 时说明存在满足题意的子矩阵。

代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include "iostream"
#include "vector"
#include "string"
#include "utility"
#include "queue"
#include "set"
#include "map"
#include "unordered_map"
#include "algorithm"
#include "cstring"
#include "stack"
#include "cmath"
#include "numeric"

using namespace std;

typedef long long ll;
const int N = 1e5 + 7;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll MOD = 1e9 + 7;
int n, m, h, w;

int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif

    cin >> n >> m;
    vector<vector<ll>> a(n + 1, vector<ll>(m + 1, -1));
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            cin >> a[i][j];
    cin >> h >> w;

    vector<vector<int>> cnt(n + 1, vector<int>(m + 1, 0));
    for (int i = 1; i <= n; i++)
        for (int j = m; j >= 1; j--) {
            if (j == m || a[i][j] != a[i][j + 1])
                cnt[i][j] = 1;
            else
                cnt[i][j] = cnt[i][j + 1] + 1;
        }

    bool ok = false;
    vector<vector<int>> b(n + 1, vector<int>(m + 1, 0));
    vector<vector<int>> c(n + 1, vector<int>(m + 1, 0));
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++) {
            if (cnt[i][j] >= h) {
                if (a[i][j] == a[i - 1][j])
                    b[i][j] = b[i - 1][j] + 1;
                else
                    b[i][j] = 1;
            }
            if (b[i][j] == w)
                ok = true;
        }
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++) {
            if (cnt[i][j] >= w) {
                if (a[i][j] == a[i - 1][j])
                    c[i][j] = c[i - 1][j] + 1;
                else
                    c[i][j] = 1;
            }
            if (c[i][j] == h)
                ok = true;
        }

    if (ok) cout << "YES";
    else cout << "NO";

    return 0;
}
updatedupdated2022-11-022022-11-02