矩阵(二维字符串哈希)

题目描述

给定一个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,M,N,B≤1000,Q≤1000
输入样例:
3 3 2 2
111
000
111
3
11
00
11
11
00
11
输出样例:
1
0
1

题解

  1. 利用字符串哈希将MN矩阵中所有AB的矩阵的哈希值算出来,存储在哈希表中。
  2. 然后,在哈希表中查询是否出现。
  3. 如何将AB矩阵快速算出来?参考一维哈希的做法。
    3.1 先将每一行的哈希值算出来。
    3.2 然后固定一个列数为B的矩阵,先算出A行,当算到A+1行的时候,加上第A+1行的哈希值,再减去第一行的哈希值,就是1~A+1行的哈希值总和。同理,2 - A+2行也可以这样算出来。

代码

#include <iostream>
#include <algorithm>
#include <unordered_set>

using namespace std;

typedef unsigned long long ULL;
const int N = 1010, M = N * N, base = 131;
char g[N];
ULL h[N][N];
ULL p[M];

ULL get(ULL f[], int l, int r)
{
    return f[r] - f[l - 1] * p[r - l + 1];
}

int main()
{
    int m, n, a, b;
    cin >> n >> m >> a >> b;
    unordered_set<ULL> S;
    p[0] = 1;
    for(int i = 1; i <= m * n; i++) p[i] = p[i - 1] * base;
    
    for(int i = 1; i <= n; i++)
    {
        scanf("%s", g + 1);
        for(int j = 1; j <= m; j++) h[i][j] = h[i][j - 1] * base + g[j] - '0';
    }
    
    for(int i = b; i <= m; i++)
    {
        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 = 0; i < a; i++)
        {
            scanf("%s", g);
            for(int j = 0; j < b; j++)
            {
                s = s * base + g[j] - '0';
            }
        }
        if (S.count(s)) puts("1");
        else puts("0");
    }
    
    return 0;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值