昨天卡了一天常数。。。然后发现吧$unsignedspace longspace 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 ",v[hs[h][l]%MOD]); } }
2019.06.12