DestinHistoire

 

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)    收藏  举报

导航