BZOJ2351[BeiJing2011]Matrix——二维hash
题目描述
给定一个M行N列的01矩阵,以及Q个A行B列的01矩阵,你需要求出这Q个矩阵哪些在原矩阵中出现过。
所谓01矩阵,就是矩阵中所有元素不是0就是1。
输入
输入文件的第一行为M、N、A、B,参见题目描述。
接下来M行,每行N个字符,非0即1,描述原矩阵。
接下来一行为你要处理的询问数Q。
接下来Q个矩阵,一共Q*A行,每行B个字符,描述Q个01矩阵。
输出
你需要输出Q行,每行为0或者1,表示这个矩阵是否出现过,0表示没有出现过,1表示出现过。
样例输入
3 3 2 2
111
000
111
3
11
00
11
11
00
11
111
000
111
3
11
00
11
11
00
11
样例输出
1
0
1
0
1
提示
对于100%的实际测试数据,M、N ≤ 1000,Q = 1000
对于40%的数据,A = 1。
对于80%的数据,A ≤ 10。
对于100%的数据,A ≤ 100。
二维hash,行和列分别用一个base,像求前缀矩阵和一样求前缀矩阵hash。因为A,B是固定的,所以暴力求出所有A*B大小的矩阵hash,用map存一下,对于每个询问O(1)判断。
#include<cstdio> #include<algorithm> #include<iostream> #include<cstring> #include<cmath> #include<map> using namespace std; int n,m; char ch[1010]; int A,B; int Q; int cnt; unsigned long long p,q; map<unsigned long long,int>b; unsigned long long h[1010][1010]; unsigned long long g[1010][1010]; int main() { scanf("%d%d%d%d",&m,&n,&A,&B); for(int i=1;i<=m;i++) { scanf("%s",ch+1); for(int j=1;j<=n;j++) { h[i][j]=h[i-1][j]*2333+h[i][j-1]*13131-h[i-1][j-1]*2333*13131+ch[j]; } } p=1; q=1; for(int i=1;i<=A;i++) { p*=2333; } for(int i=1;i<=B;i++) { q*=13131; } for(int i=A;i<=m;i++) { for(int j=B;j<=n;j++) { b[h[i][j]-h[i-A][j]*p-h[i][j-B]*q+h[i-A][j-B]*p*q]=++cnt; } } scanf("%d",&Q); while(Q--) { for(int i=1;i<=A;i++) { scanf("%s",ch+1); for(int j=1;j<=B;j++) { g[i][j]=g[i-1][j]*2333+g[i][j-1]*13131-g[i-1][j-1]*13131*2333+ch[j]; } } if(b[g[A][B]]!=0) { printf("1\n"); } else { printf("0\n"); } } }