题目链接
题意
查询小矩阵是否在大矩阵出现过,多组查询,小矩阵大小固定
思路
二维矩阵hash,将所有小矩阵可能值记录,最后
O
(
l
o
g
)
O(log)
O(log) 判断是否出现过
本题主要整个二维hash模板,模板常数特别大,需要将重复的自行优化
代码
存模板用超时代码
#include <bits/stdc++.h>
using namespace std;
#define ull unsigned long long
// 大常数写法,memset应该没有必要
const int N = 1005;
const int M = 1005;
struct Hash{
int a[N][M], n, m;
static const ull seed1 = 233, seed2 = 1789;
ull pw1[N], pw2[M], ha[N][M];
void init(int _n, int _m) { // 传入大小,下标从1开始的矩阵a
n = _n;
m = _m;
pw1[0] = pw2[0] = 1;
// memset(ha,0,sizeof(ha));
for(int i = 1; i <= m; ++i) pw1[i] = seed1*pw1[i-1];
for(int i = 1; i <= n; ++i) pw2[i] = seed2*pw2[i-1];
for(int i = 1; i <= n ; ++i)
for(int j = 1; j <= m; ++j)
ha[i][j] = ha[i][j-1]*seed1+a[i][j];
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
ha[i][j] += ha[i-1][j]*seed2;
}
ull gethash(int x1, int y1, int x2, int y2) { // 传入左上右下
--x1;
--y1;
return ha[x2][y2] - ha[x1][y2]*pw2[x2-x1] - ha[x2][y1]*pw1[y2-y1] + ha[x1][y1]*pw2[x2-x1]*pw1[y2-y1];
}
}myhash, tmp;
char s[1005];
set<ull> se;
int main() {
int n, m, a, b;
scanf("%d%d%d%d",&n,&m,&a,&b);
for(int i = 1; i <= n; ++i) {
scanf("%s",s+1);
for(int j = 1; j <= m; ++j) myhash.a[i][j] = (s[j] == '1');
}
myhash.init(n,m);
for(int i = a; i <= n; ++i) {
for(int j = b; j <= m; ++j) {
se.insert(myhash.gethash(i-a+1,j-b+1,i,j));
}
}
int q;
for(scanf("%d",&q); q; --q) {
for(int i = 1; i <= a; ++i) {
scanf("%s",s+1);
for(int j = 1; j <= b; ++j) tmp.a[i][j] = (s[j] == '1');
}
tmp.init(a,b);
ull x = tmp.gethash(1,1,a,b);
if(se.find(x) != se.end()) puts("1");
else puts("0");
}
return 0;
}
ac 代码
#include <bits/stdc++.h>
using namespace std;
#define ull unsigned long long
const int N = 1005;
const int M = 1005;
static const int seed1 = 131, seed2 = 1789;
int pw1[N], pw2[M], ha[N][M];
int gethash(int x1, int y1, int x2, int y2) { // 传入左上右下
--x1;
--y1;
return ha[x2][y2] - ha[x1][y2]*pw2[x2-x1] - ha[x2][y1]*pw1[y2-y1] + ha[x1][y1]*pw2[x2-x1]*pw1[y2-y1];
}
char s[1005][1005];
vector<int> v;
int main() {
int n, m, a, b;
scanf("%d%d%d%d",&n,&m,&a,&b);
for(int i = 1; i <= n; ++i) {
scanf("%s",s[i]+1);
}
/*****/
pw1[0] = pw2[0] = 1;
for(int i = 1; i <= m; ++i) pw1[i] = seed1*pw1[i-1];
for(int i = 1; i <= n; ++i) pw2[i] = seed2*pw2[i-1];
for(int i = 1; i <= n ; ++i)
for(int j = 1; j <= m; ++j)
ha[i][j] = ha[i][j-1]*seed1+s[i][j];
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
ha[i][j] += ha[i-1][j]*seed2;
/*****/
for(int i = a; i <= n; ++i) {
for(int j = b; j <= m; ++j) {
v.push_back(gethash(i-a+1,j-b+1,i,j));
}
}
sort(v.begin(),v.end());
int q;
for(scanf("%d",&q); q; --q) {
for(int i = 1; i <= a; ++i) {
scanf("%s",s[i]+1);
}
for(int i = 1; i <= a ; ++i)
for(int j = 1; j <= b; ++j)
ha[i][j] = ha[i][j-1]*seed1+s[i][j];
for(int i = 1; i <= a; ++i)
for(int j = 1; j <= b; ++j)
ha[i][j] += ha[i-1][j]*seed2;
int x = gethash(1,1,a,b);
int y = lower_bound(v.begin(),v.end(), x)-v.begin();
if(v[y] == x) puts("1");
else puts("0");
}
return 0;
}