BZOJ-2351 [BeiJing2011]Matrix(矩阵哈希)
题目描述
给定一个 \(n\) 行 \(m\) 列的 \(01\) 矩阵,以及 \(q\) 个 \(a\) 行 \(b\) 列的 \(01\) 矩阵,判断这 \(q\) 个矩阵哪些在原矩阵中出现过。
数据范围:\(m,n\leq 1000,q=1000,a\leq 100\)。
分析
取两个进制 \(BASE1,BASE2\),先对每一行进行 \(\text{hash}\),以新的 \(\text{hash}\) 值作为新的值,再对每一列进行 \(\text{hash}\)。仿照二维前缀和的思想,利用容斥原理可以 \(O(1)\) 获得任意子矩阵的 $\text{hash} $ 值。
代码
#include<bits/stdc++.h>
using namespace std;
const unsigned long long BASE1=131;
const unsigned long long BASE2=139;
const int N=1010;
int mp[N][N],_mp[N][N];
unsigned long long Hash[N][N];
unsigned long long pow1[N],pow2[N];
map<unsigned long long,bool> MAP;
int main()
{
int n,m,a,b;
cin>>n>>m>>a>>b;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%1d",&mp[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
Hash[i][j]=Hash[i][j-1]*BASE1+mp[i][j];
for(int j=1;j<=m;j++)
for(int i=1;i<=n;i++)
Hash[i][j]=Hash[i-1][j]*BASE2+Hash[i][j];
pow1[0]=pow2[0]=1;
for(int i=1;i<=n;i++)
pow1[i]=pow1[i-1]*BASE1;
for(int i=1;i<=m;i++)
pow2[i]=pow2[i-1]*BASE2;
for(int i=a;i<=n;i++)//(i-a+1)左上角,(j-b+1)右下角
{
for(int j=b;j<=m;j++)
{
unsigned long long temp=Hash[i][j]-Hash[i-a][j]*pow2[a]-Hash[i][j-b]*pow1[b]+Hash[i-a][j-b]*pow2[a]*pow1[b];
MAP[temp]=1;
}
}
int q;
cin>>q;
while(q--)
{
unsigned long long ans=0;
for(int i=1;i<=a;i++)
for(int j=1;j<=b;j++)
scanf("%1d",&_mp[i][j]);
for(int i=1;i<=a;i++)
for(int j=1;j<=b;j++)
ans=ans+_mp[i][j]*pow2[a-i]*pow1[b-j];
if(MAP[ans]==1)
puts("1");
else
puts("0");
}
return 0;
}
/*
//BZOJ-2462
#include<bits/stdc++.h>
using namespace std;
const unsigned long long BASE1=131;
const unsigned long long BASE2=139;
const int N=1010;
int mp[N][N],_mp[N][N];
unsigned long long Hash[N][N];
unsigned long long pow1[N],pow2[N];
unsigned long long HASH[N*N];
int main()
{
int n,m,a,b;
cin>>n>>m>>a>>b;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%1d",&mp[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
Hash[i][j]=Hash[i][j-1]*BASE1+mp[i][j];
for(int j=1;j<=m;j++)
for(int i=1;i<=n;i++)
Hash[i][j]=Hash[i-1][j]*BASE2+Hash[i][j];
pow1[0]=pow2[0]=1;
for(int i=1;i<=n;i++)
pow1[i]=pow1[i-1]*BASE1;
for(int i=1;i<=m;i++)
pow2[i]=pow2[i-1]*BASE2;
int cnt=0;
for(int i=a;i<=n;i++)//(i-a+1)左上角,(j-b+1)右下角
{
for(int j=b;j<=m;j++)
{
unsigned long long temp=Hash[i][j]-Hash[i-a][j]*pow2[a]-Hash[i][j-b]*pow1[b]+Hash[i-a][j-b]*pow2[a]*pow1[b];
HASH[++cnt]=temp;
}
}
sort(HASH+1,HASH+1+cnt);
memset(Hash,0,sizeof(Hash));
int q;
cin>>q;
while(q--)
{
for(int i=1;i<=a;i++)
for(int j=1;j<=b;j++)
scanf("%1d",&_mp[i][j]);
for(int i=1;i<=a;i++)
for(int j=1;j<=b;j++)
Hash[i][j]=Hash[i][j-1]*BASE1+_mp[i][j];
for(int j=1;j<=a;j++)
for(int i=1;i<=b;i++)
Hash[i][j]=Hash[i-1][j]*BASE2+Hash[i][j];
int temp=lower_bound(HASH+1,HASH+cnt+1,Hash[a][b])-HASH;
if(HASH[temp]==Hash[a][b])
puts("1");
else
puts("0");
}
return 0;
}*/
posted on 2020-11-14 15:16 DestinHistoire 阅读(139) 评论(0) 收藏 举报