[BZOJ]2462: [BeiJing2011]矩阵模板 二维hash

Description

给定一个M行N列的01矩阵,以及Q个A行B列的01矩阵,你需要求出这Q个矩阵哪些在
原矩阵中出现过。
所谓01矩阵,就是矩阵中所有元素不是0就是1。

题解:

二维hash,早上写了bzoj1567这道题,被fycD飞,说我写的是盗版二维hash,于是我就学了学,其实就是行搞一次,列搞一次,搞出以(1,1)为左上角的每个矩阵的hash值,最后用类似矩阵前缀和的方式求出某个子矩阵的hash值就行了。

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL unsigned long long
const int maxn=1010;
const LL mod=99999997;
const LL base1=233;
const LL base2=2333;
int m,n,a,b,q;
LL map[maxn][maxn],hash[maxn][maxn],pow1[110],pow2[110];
bool h[mod+10];
char str[maxn];
int main()
{
    scanf("%d%d%d%d",&m,&n,&a,&b);
    for(int i=1;i<=m;i++)
    {
        scanf("%s",str+1);
        for(int j=1;j<=n;j++)
        map[i][j]=str[j]-'0';
    }
    pow1[0]=pow2[0]=1;
    for(int i=1;i<=100;i++)pow1[i]=pow1[i-1]*base1,pow2[i]=pow2[i-1]*base2;
    for(int i=1;i<=m;i++)
    for(int j=1;j<=n;j++)
    hash[i][j]+=hash[i-1][j]*base1+map[i][j];
    for(int i=1;i<=m;i++)
    for(int j=1;j<=n;j++)
    hash[i][j]+=hash[i][j-1]*base2;
    for(int i=a;i<=m;i++)
    for(int j=b;j<=n;j++)
    {
        LL num=hash[i][j];
        num-=hash[i-a][j]*pow1[a];
        num-=hash[i][j-b]*pow2[b];
        num+=hash[i-a][j-b]*pow1[a]*pow2[b];
        h[num%mod]=true;
    }
    scanf("%d",&q);
    while(q--)
    {
        for(int i=1;i<=a;i++)
        {
            scanf("%s",str+1);
            for(int j=1;j<=b;j++)
            map[i][j]=str[j]-'0';
        }
        memset(hash,0,sizeof(hash));
        for(int i=1;i<=a;i++)
        for(int j=1;j<=b;j++)
        hash[i][j]+=hash[i-1][j]*base1+map[i][j];
        for(int i=1;i<=a;i++)
        for(int j=1;j<=b;j++)
        hash[i][j]+=hash[i][j-1]*base2;
        puts(h[hash[a][b]%mod]?"1":"0");
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值