给定一个 M 行 N 列的 01 矩阵,以及 Q 个 A 行 B 列的 01 矩阵,你需要求出这 Q 个矩阵哪些在原矩阵中出现过。
分析
矩阵哈希,用链表储存(其实可以不存),然后计算询问的矩阵的哈希值,在链表里寻找判断一下就好了。
代码
//=========================
// author:hliwen
// date:2019.12.28
// website:http://tyqs.kim
//=========================
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 1005
#define il inline
#define re register
#define tie0 cin.tie(0),cout.tie(0)
#define fastio ios::sync_with_stdio(false)
#define File(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout)
using namespace std;
typedef unsigned long long ull;
template <typename T> inline void read(T &x) {
T f = 1; x = 0; char c;
for (c = getchar(); !isdigit(c); c = getchar()) if (c == '-') f = -1;
for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
x *= f;
}
const int Q = 233;
const int P = 131;
const int mod = 55321;
struct edge {
ull to;
int nxt;
} e[N*N];
int m, n, a, b, q, cnt;
int head[N*N];
ull f[N][N], g[N][N], jp[N], jq[N];
char s[N];
int H(ull k) { return k % mod + 1; }
bool search(ull k) {
int u = H(k);
for (int i = head[u]; i; i = e[i].nxt) {
ull v = e[i].to;
if (v == k) return true;
}
return false;
}
void insert(ull k) {
int u = H(k);
if (!search(k))
e[++cnt].to = k, e[cnt].nxt = head[u], head[u] = cnt;
}
void init() {
jp[0] = jq[0] = 1;
for (int i = 1; i <= N; ++i)
jp[i] = jp[i-1] * P, jq[i] = jq[i-1] * Q;
}
void pre() {
for (int i = 1; i <= m; ++i)
for (int j = 1; j <= n; ++j)
f[i][j] = f[i-1][j] * P + f[i][j];
for (int i = 1; i <= m; ++i)
for (int j = 1; j <= n; ++j)
f[i][j] = f[i][j-1] * Q + f[i][j];
for (int i = a; i <= m; ++i)
for (int j = b; j <= n; ++j) {
ull now = f[i][j];
now -= f[i-a][j] * jp[a];
now -= f[i][j-b] * jq[b];
now += f[i-a][j-b] * jp[a] * jq[b];
insert(now);
}
}
ull cal() {
for (int i = 1; i <= a; ++i)
for (int j = 1; j <= b; ++j)
g[i][j] = g[i-1][j] * P + g[i][j];
for (int i = 1; i <= a; ++i)
for (int j = 1; j <= b; ++j)
g[i][j] = g[i][j-1] * Q + g[i][j];
return g[a][b];
}
int main() {
init();
read(m), read(n), read(a), read(b);
for (int i = 1; i <= m; ++i) {
scanf("%s", s + 1);
for (int j = 1; j <= n; ++j)
f[i][j] = s[j] - '0';
}
pre();
read(q);
while (q--) {
for (int i = 1; i <= a; ++i) {
scanf("%s", s + 1);
for (int j = 1; j <= b; ++j)
g[i][j] = s[j] - '0';
}
ull k = cal();
if (search(k)) puts("1");
else puts("0");
}
return 0;
}