CH1806 Matrix

题意

描述

给定一个M行N列的01矩阵(只包含数字0或1的矩阵),再执行Q次询问,每次询问给出一个A行B列的01矩阵,求该矩阵是否在原矩阵中出现过。

输入格式

第一行四个整数M,N,A,B。

接下来一个M行N列的01矩阵,数字之间没有空格。

接下来一个整数Q。

接下来Q个A行B列的01矩阵,数字之间没有空格。

输出格式

对于每个询问,输出1表示出现过,0表示没有。

样例输入

3 3 2 2
111
000
111
3
11
00
11
11
00
11

样例输出

1
0
1

数据范围与约定

对于40%的数据,A = 1。
对于80%的数据,A ≤ 10。
对于100%的数据,A ≤ 100,M, N ≤ 1000,Q ≤ 1000。

来源

CCF NOI2011 北京市选

分析

矩阵hash,原来hash可以像二维前缀和一样处理。对行,列分别看成进制数,运算与二维前缀和类似。

时间复杂度\(O(M N + Q)\)

代码

#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
    rg T data=0,w=1;
    rg char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
        data=data*10+ch-'0',ch=getchar();
    return data*w;
}
template<class T>il T read(rg T&x){
    return x=read<T>();
}
typedef unsigned long long ULL;

co int maxn=1002,pc=131,ppc=13331,mod=maxn*maxn;
ULL p1[maxn],p2[maxn],sum[maxn][maxn];
int fa,adj[mod];
char b[maxn][maxn];
struct my{
    ULL zhi;
    int next;
}bian[maxn*maxn];
void hash(ULL u){
    int x=u%mod;
    bian[++fa].zhi=u,bian[fa].next=adj[x],adj[x]=fa;
}
bool ask(ULL u){
    int x=u%mod;
    for(int i=adj[x];i;i=bian[i].next)
        if(bian[i].zhi==u) return 1;
    return 0;
}
int main(){
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    int m,n,r,c,q;
    read(m),read(n),read(r),read(c);
    for(int i=1;i<=m;++i)
        scanf("%s",b[i]+1);
    read(q);
    for(int i=1;i<=m;++i)
        for(int j=1;j<=n;++j)
            sum[i][j]=b[i][j]-'0';
    for(int i=1;i<=m;++i)
        for(int j=1;j<=n;++j)
            sum[i][j]+=sum[i-1][j]*pc;
    for(int i=1;i<=m;++i)
        for(int j=1;j<=n;++j)
            sum[i][j]+=sum[i][j-1]*ppc;
    p1[0]=p2[0]=1;
    for(int i=1;i<=r;++i)
        p1[i]=p1[i-1]*pc;
    for(int j=1;j<=c;++j)
        p2[j]=p2[j-1]*ppc;
    for(int i=r;i<=m;++i)
        for(int j=c;j<=n;++j)
            hash(sum[i][j]-sum[i-r][j]*p1[r]-sum[i][j-c]*p2[c]+sum[i-r][j-c]*p1[r]*p2[c]);
    while(q--){
        for(int i=1;i<=r;++i)
            scanf("%s",b[i]+1);
        for(int i=1;i<=r;++i)
            for(int j=1;j<=c;++j)
                sum[i][j]=b[i][j]-'0';
        for(int i=1;i<=r;++i)
            for(int j=1;j<=c;++j) sum[i][j]+=sum[i-1][j]*pc;
        for(int i=1;i<=r;++i)
            for(int j=1;j<=c;++j) sum[i][j]+=sum[i][j-1]*ppc;
        puts(ask(sum[r][c])?"1":"0");
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/autoint/p/10417673.html