二维矩阵hash
给定一个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,M,N,B≤1000,Q≤1000
输入样例:
3 3 2 2
111
000
111
3
11
00
11
11
00
11
输出样例:
1
0
1
#include <bits/stdc++.h>
using namespace std ;
typedef unsigned long long ll ;
const int N = 1010 ;
ll h[N][N] , p[N * N] ;
const int base = 131 ;
ll get(ll f[] , ll l , ll r)
{
return f[r] - f[l - 1] * p[r - l + 1] ;
}
int main()
{
p[0] = 1 ;
for(int i = 1 ; i < N * N ;i ++) p[i] = p[i - 1] * base ;
int n , m , a , b ;
char str[N] ;
cin >> n >> m >> a >> b ;
for(int i = 1; i <= n ;i ++)
{
scanf("%s" , str + 1) ;
for(int j = 1 ;j <= m ;j ++)
h[i][j] = h[i][j - 1] * base + str[j] - '0' ;
}
unordered_map<ll , int> mp ;
for(int i = b ; i <= m ;i ++)
{
ll s = 0 ;
for(int j = 1 ; j <= n ;j ++)
{
int l = i - b + 1 , r = i ;
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) mp[s] = 1 ;
}
}
int Q ;
cin >> Q ;
while(Q --)
{
ll s = 0 ;
for(int i = 1 ;i <= a ;i ++)
{
scanf("%s" , str + 1) ;
for(int j = 1; j <= b ;j ++)
s = s * base + str[j] - '0' ;
}
if(mp[s]) cout << "1" << endl ;
else cout << "0" << endl ;
}
return 0 ;
}
每次做题提醒自己:题目到底有没有读懂,有没有分析彻底、算法够不够贪心、暴力够不够优雅。