「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;
}

猜你喜欢

转载自www.cnblogs.com/hlw1/p/12202819.html
今日推荐