题目描述
题解
朴素的暴力就能A掉,数据弱。
学习了一下矩阵hash。
感觉非常玄学;刚开始把每一行转化成2进制数,然后把所有的行合并起来转化成
2b
进制数,就得到了一个矩阵的hash值。
算出来所有小矩阵的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");
}
}
总结
%的数还是要搞懂一下。