给定一个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
思路:把a*b矩阵 哈希为数字 存到 unorder_set
怎样hash:先把每行前缀+hash 掉用函数可以 求出区间hash值
#include<unordered_set>
#include<iostream>
#include<algorithm>
using namespace std;
typedef unsigned long long ull;
const int N=1010;
ull g[N][N],p[N*N];
int m,n,a,b;
char str[N];
//求第i行区间【l,r】 的hash值
ull calc(ull arr[],int l,int r){
return arr[r]-arr[l-1]*p[r-l+1];
}
int main(){
cin>>m>>n>>a>>b;
p[0]=1;
for(int i=1;i<=n*m;i++) p[i]=p[i-1]*131;
for(int i=1;i<=m;i++){
cin>>str+1;
for(int j=1;j<=n;j++) g[i][j]=g[i][j-1]*131+str[j]-'0';
}
unordered_set<ull> S;
for(int i=b;i<=n;i++){
int l=i-b+1,r=i;
ull s=0;
for(int j=1;j<=m;j++){
//整体下移一行 即 位数增大b倍
s=s*p[b]+calc(g[j],l,r);
if(j>a) s-=calc(g[j-a],l,r)*p[a*b];
if(j>=a) S.insert(s);
}
}
int q;
cin>>q;
while(q--){
ull num=0;
for(int i=1;i<=a;i++)
{
cin>>str+1;
for(int j=1;j<=b;j++){
num=num*131+str[j]-'0';
}
}
if(S.count(num)) cout<<'1'<<endl;
else cout<<'0'<<endl;
}
return 0;
}
posted on
浙公网安备 33010602011771号