「BZOJ 2351」Matrix

给定一个 M 行 N 列的 01 矩阵,以及 Q 个 A 行 B 列的 01 矩阵,你需要求出这 Q 个矩阵哪些在原矩阵中出现过。

BZOJ

分析

矩阵哈希,用链表储存(其实可以不存),然后计算询问的矩阵的哈希值,在链表里寻找判断一下就好了。

代码

//=========================
//  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;
}
posted @ 2020-01-16 19:04  小蒟蒻hlw  阅读(148)  评论(0)    收藏  举报