Matrix(二维hash)
題目鏈接
文章目錄
- 題目描述
- 題意:
- 題解
- 代碼:
題目描述
給定一個M行N列的01矩陣(只包含數(shù)字0或1的矩陣),再執(zhí)行Q次詢問,每次詢問給出一個A行B列的01矩陣,求該矩陣是否在原矩陣中出現(xiàn)過。
輸入描述: 第一行四個整數(shù)M,N,A,B。 接下來一個M行N列的01矩陣,數(shù)字之間沒有空格。 接下來一個整數(shù)Q。
接下來Q個A行B列的01矩陣,數(shù)字之間沒有空格。 輸出描述: 對于每個詢問,輸出1表示出現(xiàn)過,0表示沒有。
示例1
輸入
輸出
1 0 1備注:
對于40%的數(shù)據(jù),A = 1。
對于80%的數(shù)據(jù),A≤10。
對于100%的數(shù)據(jù),A≤100,M,N≤1000,Q≤1000。
題意:
給你個MN的二維矩陣,然后給你個AB的二維矩陣,問后者是否在前者出現(xiàn)過
題解
毫無疑問用hash
我們先想一個問題:
一個長為L的字符串a(chǎn),問長度為len(len<L)的字符串b在a中出現(xiàn)過嗎?
這個怎么做?
我們可以將a中長度為len的部分求出hash并放進(jìn)哈希表,然后求出b的hash,進(jìn)行比較即可
其實本題就是將一維問題轉(zhuǎn)化成二維
我們將n * m的矩形中所有大小為a * b的矩形哈希一下并放到哈希表中,然后給出矩陣后,直接O(1)查找就可以了
求矩陣的hash的步驟:
先求出每一行前綴的hash,然后固定矩陣的一邊長度b,求出長度為b的邊的hash值,然后從這一行向下延伸a行,求出這a行對應(yīng)的長度為b的hash值。當(dāng)長度大于a后,就將最上面一行刪去,始終保持為 a * b 的矩陣。
代碼:
#include <bits/stdc++.h> using namespace std; const int maxn=1005; typedef unsigned long long ull; ull hash1[maxn][maxn]; ull base[maxn*maxn]; int base1=13; char c[maxn]; ull get(ull hash1[],int l,int r) {return hash1[r]-hash1[l-1]*base[r-l+1]; } int q; int n,m,a,b; int main(){cin>>n>>m>>a>>b;base[0]=1;for(int i=1;i<=n*m;i++) base[i]=base[i-1]*base1;//素數(shù)倍數(shù),用于查詢子串哈希值 for(int i=1;i<=n;i++){scanf("%s",c+1);for(int j=1;j<=m;j++) hash1[i][j]=hash1[i][j-1]*base1+c[j]-'0';//求取每一行前綴哈希值 }unordered_set<ull> s;for(int i=b;i<=m;i++){ull x=0;int l=i-b+1,r=i;for(int j=1;j<=n;j++){x=x*base[b]+get(hash1[j],l,r);// 加上當(dāng)前行的hash值 if(j>a) x-=get(hash1[j-a],l,r)*base[a*b];// 如果超行了,刪去最上面一行 if(j>=a){s.insert(x);//用map來存哈希值,方便后面的判斷是否存在 }}}cin>>q;while(q--){ull x=0;for(int i=0;i<a;i++){scanf("%s",c);for(int j=0;j<b;j++){x=x*base1+c[j]-'0';//將所給的矩陣轉(zhuǎn)化成hash }}if(s.count(x))//利用map性質(zhì)查詢是否有這個數(shù) cout<<"1"<<endl;else cout<<"0"<<endl;}return 0; }不過這樣做,好像超內(nèi)存了。。。
可以手寫map會好些
總結(jié)
以上是生活随笔為你收集整理的Matrix(二维hash)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么宣传网页(怎么宣传网页内容)
- 下一篇: 牛客网【每日一题】5月19日题目精讲 比