题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2462
题意:
[Submit][Status][Discuss]
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
解法:二维Hash,BASE取得过大会TLE
//BZOJ 2426
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1010;
const unsigned int BASE1 = 121;
const unsigned int BASE2 = 131;
const int mod = 99999997;
int n, m, a, b, q;
unsigned int hash1[maxn][maxn], hash2[maxn][maxn];
unsigned int bas1[maxn], bas2[maxn];
bool v[100000000];
unsigned int getHash()
{
for(int i = 1; i <= a; i++)
for(int j = 1; j <= b; j++)
hash2[i][j] += hash2[i-1][j]*BASE1;
for(int i = 1; i <= a; i++){
for(int j = 1; j <= b; j++){
hash2[i][j] += hash2[i][j-1]*BASE2;
}
}
return hash2[a][b];
}
void input()
{
scanf("%d%d%d%d", &n, &m, &a, &b);
}
void work()
{
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
scanf("%1d", &hash1[i][j]);
}
}
bas1[0] = bas2[0] = 1;
for(int i = 1; i <= 100; i++) bas1[i] = bas1[i-1]*BASE1, bas2[i] = bas2[i-1]*BASE2;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
hash1[i][j] += hash1[i-1][j]*BASE1;
}
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
hash1[i][j] += hash1[i][j-1]*BASE2;
}
}
for(int i = a; i <= n; i++){
for(int j = b; j <= m; j++){
unsigned int h = hash1[i][j];
h -= hash1[i-a][j]*bas1[a];
h -= hash1[i][j-b]*bas2[b];
h += hash1[i-a][j-b]*bas1[a]*bas2[b];
v[h%mod]=1;
}
}
}
void output()
{
scanf("%d", &q);
while(q--)
{
for(int i = 1; i <= a; i++){
for(int j = 1; j <= b; j++){
scanf("%1d", &hash2[i][j]);
}
}
unsigned x = getHash() % mod;
if(v[x]) puts("1");
else puts("0");
}
}
int main()
{
input();
work();
output();
return 0;
}