给定一个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 2019-08-08 17:10  谁是凶手1703  阅读(123)  评论(0)    收藏  举报