156. 矩阵[二维的hash]

给定一个M行N列的01矩阵(只包含数字0或1的矩阵),再执行Q次询问,每次询问给出一个A行B列的01矩阵,求该矩阵是否在原矩阵中出现过。

输入格式

第一行四个整数M,N,A,B。

接下来一个M行N列的01矩阵,数字之间没有空格。

接下来一个整数Q。

接下来Q个A行B列的01矩阵,数字之间没有空格。

输出格式

对于每个询问,输出1表示出现过,0表示没有出现过。

数据范围

A≤100<?XML:NAMESPACE PREFIX = "[default] http://www.w3.org/1998/Math/MathML" NS = "http://www.w3.org/1998/Math/MathML" />A≤100,M,N,B≤1000M,N,B≤1000,Q≤1000Q≤1000

输入样例:
3 3 2 2
111
000
111
3
11
00
11
11
00
11
输出样例:
1
0
1

首先,此题是一维hash的拓展。
我们可以通过先将每一行hash完成,然后通过枚举a,b大小的矩阵,计算hash值,通过公式推导,
a列到a+1列的公式是,s = s*p^b + get(h[j], l, r);也就是该行的hash值。
最后给出代码:
#include <iostream>
#include <algorithm>
#include <unordered_set>
using namespace std;

using ULL = unsigned long long;
const int N = 1010, M = N*N, base = 131;
char str[N];
ULL h[N][N], p[M];
int n, m, a, b;
ULL get(ULL h[], int l, int r){
    return h[r] - h[l - 1] * p[r - l + 1];
}

int main() {
    cin >> n >> m >> a >> b;
    p[0] = 1;
    for(int i = 1; i <= n*m; ++ i) p[i] = p[i-1] * base;//对应的进制数的幂
    for(int i = 1; i <= n; ++ i) {//处理行并hash
        cin >> (str+1);
        for(int j = 1; j <= m; ++ j)h[i][j] = h[i][j - 1] * base + str[j] - '0';
    }
    unordered_set<ULL> S;
    for(int i = b; i <= m; ++ i) {//处理每个矩形hash值。
        ULL s = 0;
        int l = i - b + 1, r = i;
        for(int j = 1; j <= n; ++ j){
            s = s * p[b] + get(h[j], l, r);
            if(j > a) s -= get(h[j - a], l, r) * p[a*b];
            if(j >= a) S.insert(s);
        }
    }

    int k;
    cin >> k;
    while(k --) {
        ULL s = 0;
        for(int i = 1; i <= a; ++ i) {//处理输入要查找的矩形,计算hash值
            cin >> (str+1);
            for(int j = 1; j <= b; ++ j) s = s*base + str[i] - '0';
        }
        if(S.count(s))puts("1");//看是否在集合中
        else puts("0");
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/rstz/p/13385539.html
156