牛客-Matrix(二維Hash-矩陣匹配)
阿新 • • 發佈:2020-07-24
題目連結:https://ac.nowcoder.com/acm/problem/51003
題目描述
給定一個M行N列的01矩陣(只包含數字0或1的矩陣),再執行Q次詢問,每次詢問給出一個A行B列的01矩陣,求該矩陣是否在原矩陣中出現過。
輸入描述:
第一行四個整數M,N,A,B。
接下來一個M行N列的01矩陣,數字之間沒有空格。
接下來一個整數Q。
接下來Q個A行B列的01矩陣,數字之間沒有空格。
輸出描述:
對於每個詢問,輸出1表示出現過,0表示沒有。
輸入
3 3 2 2
111
000
111
3
11
00
11
11
00
11
輸出
1
0
1
備註:
對於40%的資料,A = 1。
對於80%的資料,A≤10。
對於100%的資料,A≤100,M,N≤1000,Q≤1000。
emmm,就是個二維Hash的板子題,我們先對每行的字首維護一下Hash值,最對每列維護每行字首的字首值。其維護過程如下:(nm這是真的難受,縮排太大了,每次要手動搞一下QAQ)
void get_hash(int n,int m,int type) { for (int i=1; i<=n; i++) for (int j=1; j<=m; j++) if (type) hashs[i][j]=hashs[i][j-1]*base1+s[i][j]; else sub_hash[i][j]=sub_hash[i][j-1]*base1+s[i][j]; for (int j=1; j<=m; j++) for (int i=1; i<=n; i++) if (type) hashs[i][j]=hashs[i-1][j]*base2+hashs[i][j]; else sub_hash[i][j]=sub_hash[i-1][j]*base2+sub_hash[i][j]; }
然後我們將模板矩陣的每個A行B列的子矩陣的Hash值算出來,這裡有點類似於字首和的:
for (int i=a; i<=n; i++)
for (int j=b; j<=m; j++) {
ull sb=hashs[i][j]-hashs[i-a][j]*pw2[a]-hashs[i][j-b]*pw1[b]+hashs[i-a][j-b]*pw2[a]*pw1[b];
mos[++cnt]=sb;
}
以下是AC程式碼:
#include <bits/stdc++.h> using namespace std; const int mac=1e3+10; const int base1=131,base2=137; typedef unsigned long long ull; char s[mac][mac]; ull hashs[mac][mac],mos[mac*mac],sub_hash[120][mac]; ull pw1[mac],pw2[mac]; void get_hash(int n,int m,int type) { for (int i=1; i<=n; i++) for (int j=1; j<=m; j++) if (type) hashs[i][j]=hashs[i][j-1]*base1+s[i][j]; else sub_hash[i][j]=sub_hash[i][j-1]*base1+s[i][j]; for (int j=1; j<=m; j++) for (int i=1; i<=n; i++) if (type) hashs[i][j]=hashs[i-1][j]*base2+hashs[i][j]; else sub_hash[i][j]=sub_hash[i-1][j]*base2+sub_hash[i][j]; } int main(int argc, char const *argv[]) { 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); get_hash(n,m,1); int cnt=0; pw1[0]=pw2[0]=1; for (int i=1; i<=max(n,m); i++) pw1[i]=pw1[i-1]*base1,pw2[i]=pw2[i-1]*base2; for (int i=a; i<=n; i++){ for (int j=b; j<=m; j++){ ull sb=hashs[i][j]-hashs[i-a][j]*pw2[a]-hashs[i][j-b]*pw1[b]+hashs[i-a][j-b]*pw2[a]*pw1[b]; mos[++cnt]=sb; } } sort(mos+1,mos+cnt+1); int q; scanf ("%d",&q); while (q--){ for (int i=1; i<=a; i++) scanf ("%s",s[i]+1); get_hash(a,b,0); int flag=0; int pos=lower_bound(mos+1,mos+1+cnt,sub_hash[a][b])-mos-1; if (pos<cnt && mos[pos+1]==sub_hash[a][b]) flag=1; if (flag) printf("1\n"); else printf("0\n"); } return 0; }