Description

给定一个M行N列的01矩阵,以及Q个A行B列的01矩阵,你需要求出这Q个矩阵哪些在
原矩阵中出现过。
   所谓01矩阵,就是矩阵中所有元素不是0就是1。 
 

Input

输入文件的第一行为M、N、A、B,参见题目描述。
接下来M行,每行N个字符,非0即1,描述原矩阵。
接下来一行为你要处理的询问数Q。
接下来Q个矩阵,一共Q*A行,每行B个字符,描述Q个01矩阵。 
 

Output

你需要输出Q行,每行为0或者1,表示这个矩阵是否出现过,0表示没有出现过,1表
示出现过。

Sample Input

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

Sample Output

1
0
1

HINT

对于100%的数据,N,M<=1000 A,B<=100

​传送门​

200题庆贺~~



终于会二维哈希了……

就是先每一行各自哈希一遍,

然后换一个哈希的种子,每一列再哈希一遍。

对于每个(x,y),假设行种子为p,列种子为q,

那么(x,y)的哈希值“系数”应该是p^(x-1)*q^(y-1)

分别预处理出p和q的n次方,

根据这个我们可以直接O(1)求出某一个矩阵的哈希值了。

然后这道题的话,可以把所有A*B的哈希值提取出来,

每次输入一个A*B的矩阵,判断之前有没有提取出来过这个哈希值就好了。


对于bzoj2462……不能用map……会T……(可能是我写渣了),

那就设个模数然后直接数组哈希就行了,数据水可以过的

对于bzoj2351则不可以……TAT一开始贴了,换了几个模数和种子都WA2333

然后用了map!。。。竟然没T就过了。。= =



数组哈希:


#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int
N=1005,
seed1=1313,
seed2=1313113,
Mod=7461037;
int n,m,A,B,len;
int app[N],sfac1[N],sfac2[N];
int hash[N][N],Map[Mod];
char s[N][N];
void HASH(int n,int m){
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
hash[i][j]=(ll)hash[i][j-1]*seed1%Mod+s[i][j]-'0';
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
hash[i][j]=((ll)hash[i-1][j]*seed2%Mod+hash[i][j])%Mod;
}
void Pre(){
sfac1[0]=sfac2[0]=1;
for (int i=1;i<N;i++)
sfac1[i]=(ll)sfac1[i-1]*seed1%Mod,
sfac2[i]=(ll)sfac2[i-1]*seed2%Mod;
HASH(n,m);
for (int i=A;i<=n;i++)
for (int j=B;j<=m;j++){
int tmp=(ll)hash[i][j]
-(ll)hash[i][j-B]*sfac1[B]%Mod
-(ll)hash[i-A][j]*sfac2[A]%Mod
+(ll)hash[i-A][j-B]*sfac1[B]%Mod*sfac2[A]%Mod;
while (tmp<0) tmp+=Mod;
tmp%=Mod;
Map[tmp]=1;
}
}
int main(){
scanf("%d%d%d%d",&n,&m,&A,&B);
for (int i=1;i<=n;i++) scanf("%s",s[i]+1);
Pre();
int Q;scanf("%d",&Q);
while (Q--){
for (int i=1;i<=A;i++) scanf("%s",s[i]+1);
HASH(A,B);
printf("%d\n",Map[hash[A][B]]);
}
return 0;
}

map哈希(自然溢出):

#include<bits/stdc++.h>
#define uint unsigned int
using namespace std;
const int
N=1005;
const uint
seed1=131,
seed2=1331113;
map<int,bool>MAP;
int n,m,A,B;
uint hash[N][N],sfac1[N],sfac2[N];
char s[N][N];
void HASH(int n,int m){
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
hash[i][j]=hash[i][j-1]*seed1+s[i][j]-'0';
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
hash[i][j]=hash[i-1][j]*seed2+hash[i][j];
}
void Pre(){
int tmp=max(n,m);
sfac1[0]=sfac2[0]=1;
for (int i=1;i<tmp;i++)
sfac1[i]=sfac1[i-1]*seed1,sfac2[i]=sfac2[i-1]*seed2;
HASH(n,m);
for (int i=A;i<=n;i++)
for (int j=B;j<=m;j++){
uint tmp=hash[i][j]-hash[i][j-B]*sfac1[B]-hash[i-A][j]*sfac2[A]
+hash[i-A][j-B]*sfac1[B]*sfac2[A];
MAP[tmp]=1;
}
}
int main(){
scanf("%d%d%d%d",&n,&m,&A,&B);
for (int i=1;i<=n;i++) scanf("%s",s[i]+1);
Pre();
int Q;scanf("%d",&Q);
while (Q--){
for (int i=1;i<=A;i++) scanf("%s",s[i]+1);
HASH(A,B);
if (MAP[hash[A][B]]) puts("1");
else puts("0");
}
return 0;
}