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");
}
}