BZOJ 2462 [BeiJing2011]矩阵模板 矩阵哈希

昨天卡了一天常数。。。然后发现吧$unsigned\space long\space long$改成$unsigned$就可以过了$qwq$


先把每一行的前缀哈希求出,然后再竖着把每个前缀哈希值哈希起来(相当于二维前缀哈希)

注意横着和竖着哈希的$Base$不能相同

#include<cstdio>
#include<iostream>
#define ll long long
#define ull unsigned 
#define R register int
using namespace std;
const int B=3,B2=5,N=1010;
namespace Fread {
    static char B[1<<15],*S=B,*D=B;
    #define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++)
    inline int g() {
        R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
        do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
    } inline bool isempty(const char& ch) {return ch<=36||ch>=127;}
    inline void gs(char* s) {register char ch; while(isempty(ch=getchar())); do *s++=ch; while(!isempty(ch=getchar()));}
}using Fread::g; using Fread::gs;
int n,m,h,l;
ull hsh[N][N],p[N],p2[N],hs[N/10][N/10];
char s[N][N],ss[N/10][N/10];
const int MOD=99999971;
bool v[MOD];
signed main() { 
    p[0]=p2[0]=1; for(R i=1;i<=1000;++i) p[i]=p[i-1]*B; for(R i=1;i<=1000;++i) p2[i]=p2[i-1]*B2;
    n=g(),m=g(),h=g(),l=g(); for(R i=1;i<=n;++i) gs(s[i]+1);
    for(R i=1;i<=n;++i) for(R j=1;j<=m;++j) hsh[i][j]=hsh[i][j-1]*B+s[i][j]-'0';
    for(R i=1;i<=n;++i) for(R j=1;j<=m;++j) hsh[i][j]=hsh[i-1][j]*B2+hsh[i][j];
    for(R i=h;i<=n;++i) for(R j=l;j<=m;++j) v[(hsh[i][j]-hsh[i-h][j]*p2[h]-hsh[i][j-l]*p[l]+hsh[i-h][j-l]*p2[h]*p[l])%MOD]=true;
    for(R q=g();q;--q) {
        for(R i=1;i<=h;++i) gs(ss[i]+1);
        for(R i=1;i<=h;++i) for(R j=1;j<=l;++j) hs[i][j]=hs[i][j-1]*B+ss[i][j]-'0';
        for(R i=1;i<=h;++i) for(R j=1;j<=l;++j) hs[i][j]=hs[i-1][j]*B2+hs[i][j];
        printf("%d\n",v[hs[h][l]%MOD]);
    }
}

2019.06.12

 

posted @ 2019-06-12 23:53  LuitaryiJack  阅读(...)  评论(...编辑  收藏