• AcWing 156. 矩阵 (哈希二维转一维查询)打卡


    给定一个M行N列的01矩阵(只包含数字0或1的矩阵),再执行Q次询问,每次询问给出一个A行B列的01矩阵,求该矩阵是否在原矩阵中出现过。

    输入格式

    第一行四个整数M,N,A,B。

    接下来一个M行N列的01矩阵,数字之间没有空格。

    接下来一个整数Q。

    接下来Q个A行B列的01矩阵,数字之间没有空格。

    输出格式

    对于每个询问,输出1表示出现过,0表示没有出现过。

    数据范围

    A100A≤100,M,N,B1000M,N,B≤1000,Q1000Q≤1000

    输入样例:

    3 3 2 2
    111
    000
    111
    3
    11
    00
    11
    11
    00
    11
    

    输出样例:

    1
    0
    1

    题意:判断查询时输入的矩阵是否是上面那个的子矩阵
    思路:哈希可以用快速判断是否相等,我们可以预处理出上面大矩阵的所有小矩阵的哈希值,我们每个位置再去遍历肯定不行那样就是(n*m)^2,会超时,我们可以利用哈希的加减性质,我们首先计算出每一行的前缀哈希值
    然后我们再预处理子矩阵的时候利用哈希值合并的性质只用遍历每一行,这样就省去了一个m,不会超时,然后用map保留下来所有的值,后面查询时候也计算每个矩阵的哈希值即可,判断map中是否存在
    因为我们的哈希只能记录一维的哈希值,二维的记录会极大可能发生冲突,只能用二维转化成一维再去记录,切记要用unsigned long long ,可能很多人会问为什么不用mod,因为ull自带mod功能
    #include<bits/stdc++.h>
    #define maxn 1005
    #define mod 1000000007
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    ll m,n,a,b;
    char str[maxn][maxn],s[maxn][maxn];
    ull dp[maxn][maxn];
    ull f[maxn];
    map<ull,ll> mp; 
    void hash_code(){//记录所有行的前缀哈希值
        for(int i=1;i<=m;i++){
            f[0]=1;
            for(int j=1;j<=n;j++){
                dp[i][j]=dp[i][j-1]*131+str[i][j]-'0'+1; 
                if(i==1) f[j]=f[j-1]*131;
            }
        }
    }
    void init(){
        for(int i=1;i<=m-a+1;i++){
            for(int j=1;j<=n-b+1;j++){
                ull sum=0;
                for(int k=i;k<i+a;k++){//利用哈希合并性质省去一层循环
                    sum=sum*f[b]+dp[k][j+b-1]-dp[k][j-1]*f[b];
                }
                mp[sum]=1;
                //printf("%llu
    ",sum);
            }
        }
    }
    int main(){
        scanf("%lld%lld%lld%lld",&m,&n,&a,&b);
        for(int i=1;i<=m;i++){
            scanf("%s",str[i]+1);
        }
        hash_code();
        init();
        ll q;
        scanf("%lld",&q);
        for(int i=0;i<q;i++){
            for(int j=1;j<=a;j++){
                scanf("%s",s[j]+1);
            }
            ull sum=0;
            for(int j=1;j<=a;j++){
                for(int k=1;k<=b;k++){
                    sum=sum*131+s[j][k]-'0'+1;
                }
            }
            //printf("%llu
    ",sum);
            if(mp[sum]) printf("1
    ");
            else printf("0
    ");
        } 
    } 
  • 相关阅读:
    Ext学习-HelloWorld以及基础环境搭建
    简易复选框样式设置
    浏览器加载js文件顺序
    handsontable前端excel学习笔记
    前端构建工具里babel-polyfill的使用问题
    前端后端分离,怎么解决SEO优化的问题呢?
    关于babel和babel-polyfill
    一段node代码的解读
    express笔记
    mac下通过brew安装的Nginx在哪
  • 原文地址:https://www.cnblogs.com/Lis-/p/10902084.html
Copyright © 2020-2023  润新知