[BZOJ2462]矩陣模板(暴力||矩陣hash)
阿新 • • 發佈:2018-12-30
題目描述
題解
樸素的暴力就能A掉,資料弱。
學習了一下矩陣hash。
感覺非常玄學;剛開始把每一行轉化成2進位制數,然後把所有的行合併起來轉化成
算出來所有小矩陣的hash值,然後把大矩陣裡的每一個小矩陣的hash值也算出來,查詢就行了。
很玄學的是%的數,貌似讓它直接炸掉就可以了= =兩次模的是一樣的數?
TA說概率很科學。
程式碼
暴力
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int n,m,a,b,q;
int A[1005][1005],B[1005][1005];
bool flag;
char s[1005];
int main(){
scanf("%d%d%d%d\n",&n,&m,&a,&b);
for (int i=1;i<=n;++i){
gets(s);
for (int j=1;j<=m;++j)
A[i][j]=s[j-1]-'0';
}
scanf("%d\n",&q);
while (q--){
for (int i=1;i<=a;++i){
gets(s);
for (int j=1;j<=b;++j)
B[i][j]=s[j-1]-'0';
}
for (int i=1;i<=n-a+1;++i)
for (int j=1;j<=m-b+1;++j){
flag=true;
for (int k=1;k<=a;++k)
for (int l=1;l<=b;++l)
if (A[i+k-1][j+l-1]!=B[k][l]){
flag=false;
k=a+1;
l=b+1;
}
if (flag) {
i=n+1;
j=m+1;
}
}
if (flag) printf("1\n");
else printf("0\n");
}
}
hash
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
using namespace std;
#define ll unsigned long long
const int max_n=1e3+5;
int n,m,a,b,q;
char s[max_n];
int A[max_n][max_n],B[max_n][max_n];
ll S;
ll mt[max_n][max_n],squ[max_n];
ll mi2[max_n],miS[max_n];
ll hash[max_n*max_n],temp;
int main(){
scanf("%d%d%d%d\n",&n,&m,&a,&b);
S=1<<b;
int N=max(a,b);
mi2[0]=1;
for (int i=1;i<=N;++i)
mi2[i]=mi2[i-1]*2;
miS[0]=1;
for (int i=1;i<=N;++i)
miS[i]=miS[i-1]*S;
for (int i=1;i<=n;++i){
gets(s);
for (int j=1;j<=m;++j)
A[i][j]=s[j-1]-'0';
}
for (int i=1;i<=n;++i){
ll ans=0;
for (int j=1;j<=b;++j)
ans=ans+A[i][j]*mi2[b-j];
mt[i][1]=ans;
for (int j=2;j<=m-b+1;++j){
ll head=A[i][j-1];
ll tail=A[i][j+b-1];
ans=ans*2-head*mi2[b]+tail;
mt[i][j]=ans;
}
}
for (int i=1;i<=m-b+1;++i){
ll ans=0;
for (int j=1;j<=a;++j)
ans+=mt[j][i]*miS[a-j];
hash[++temp]=ans;
for (int j=2;j<=n-a+1;++j){
ll head=mt[j-1][i];
ll tail=mt[j+a-1][i];
ans=ans*S-head*miS[a]+tail;
hash[++temp]=ans;
}
}
temp=unique(hash+1,hash+temp+1)-hash-1;
sort(hash+1,hash+temp+1);
scanf("%d\n",&q);
while (q--){
if (n<a||m<b){
puts("0");
continue;
}
for (int i=1;i<=a;++i){
gets(s);
for (int j=1;j<=b;++j)
B[i][j]=s[j-1]-'0';
}
for (int i=1;i<=a;++i){
ll ans=0;
for (int j=1;j<=b;++j)
ans=ans+B[i][j]*mi2[b-j];
squ[i]=ans;
}
ll ans=0;
for (int i=1;i<=a;++i)
ans+=squ[i]*miS[a-i];
if (hash[ lower_bound(hash+1,hash+temp+1,ans)-hash ]==ans) puts("1");
else puts("0");
}
}
總結
%的數還是要搞懂一下。