给定一个M行N列的01矩阵(只包含数字0或1的矩阵),再执行Q次询问,每次询问给出一个A行B列的01矩阵,求该矩阵是否在原矩阵中出现过。
输入格式
第一行四个整数M,N,A,B。
接下来一个M行N列的01矩阵,数字之间没有空格。
接下来一个整数Q。
接下来Q个A行B列的01矩阵,数字之间没有空格。
输出格式
对于每个询问,输出1表示出现过,0表示没有出现过。
数据范围
A≤100<?XML:NAMESPACE PREFIX = "[default] http://www.w3.org/1998/Math/MathML" NS = "http://www.w3.org/1998/Math/MathML" />A≤100,M,N,B≤1000M,N,B≤1000,Q≤1000Q≤1000
输入样例:
3 3 2 2
111
000
111
3
11
00
11
11
00
11
输出样例:
1
0
1
首先,此题是一维hash的拓展。
我们可以通过先将每一行hash完成,然后通过枚举a,b大小的矩阵,计算hash值,通过公式推导,
a列到a+1列的公式是,s = s*p^b + get(h[j], l, r);也就是该行的hash值。
最后给出代码:
#include <iostream> #include <algorithm> #include <unordered_set> using namespace std; using ULL = unsigned long long; const int N = 1010, M = N*N, base = 131; char str[N]; ULL h[N][N], p[M]; int n, m, a, b; ULL get(ULL h[], int l, int r){ return h[r] - h[l - 1] * p[r - l + 1]; } int main() { cin >> n >> m >> a >> b; p[0] = 1; for(int i = 1; i <= n*m; ++ i) p[i] = p[i-1] * base;//对应的进制数的幂 for(int i = 1; i <= n; ++ i) {//处理行并hash cin >> (str+1); for(int j = 1; j <= m; ++ j)h[i][j] = h[i][j - 1] * base + str[j] - '0'; } unordered_set<ULL> S; for(int i = b; i <= m; ++ i) {//处理每个矩形hash值。 ULL s = 0; int l = i - b + 1, r = i; for(int j = 1; j <= n; ++ j){ s = s * p[b] + get(h[j], l, r); if(j > a) s -= get(h[j - a], l, r) * p[a*b]; if(j >= a) S.insert(s); } } int k; cin >> k; while(k --) { ULL s = 0; for(int i = 1; i <= a; ++ i) {//处理输入要查找的矩形,计算hash值 cin >> (str+1); for(int j = 1; j <= b; ++ j) s = s*base + str[i] - '0'; } if(S.count(s))puts("1");//看是否在集合中 else puts("0"); } return 0; }