题意
题解
对 M × M M\times M M×M 矩阵中的 A × B A\times B A×B 子矩阵进行二维哈希,具体思路为先按行求解宽为 B B B 的子区间的哈希值,再按列求解高为 A A A 的子矩阵哈希值。使用 s e t set set 维护出现的子矩阵,总时间复杂度 O ( ( N M + Q ) log ( N M ) ) O((NM+ Q)\log (NM)) O((NM+Q)log(NM))。
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int maxn = 1005;
int N, M, A, B, Q;
char mat[maxn][maxn];
ull F[maxn][maxn], G[maxn][maxn];
set<ull> st;
void Hash(char mat[maxn][maxn], int m, int n)
{
const ull b1 = 9973, b2 = 13331;
ull t1 = 1;
for (int i = 0; i < B; ++i)
t1 *= b1;
for (int i = 0; i < m; ++i)
{
ull e = 0;
for (int j = 0; j < B; ++j)
e = e * b1 + mat[i][j];
for (int j = 0; j + B <= n; ++j)
{
F[i][j] = e;
if (j + B < n)
e = e * b1 - mat[i][j] * t1 + mat[i][j + B];
}
}
ull t2 = 1;
for (int i = 0; i < A; ++i)
t2 *= b2;
for (int j = 0; j + B <= n; ++j)
{
ull e = 0;
for (int i = 0; i < A; ++i)
e = e * b2 + F[i][j];
for (int i = 0; i + A <= m; ++i)
{
G[i][j] = e;
if (i + A < m)
e = e * b2 - F[i][j] * t2 + F[i + A][j];
}
}
}
int main()
{
scanf("%d%d%d%d", &M, &N, &A, &B);
for (int i = 0; i < M; ++i)
scanf(" %s", mat[i]);
Hash(mat, M, N);
for (int i = 0; i + A <= M; ++i)
for (int j = 0; j + B <= N; ++j)
st.insert(G[i][j]);
scanf("%d", &Q);
while (Q--)
{
for (int i = 0; i < A; ++i)
scanf(" %s", mat[i]);
Hash(mat, A, B);
printf("%d\n", (int)st.count(G[0][0]));
}
return 0;
}