二维哈希-矩阵

二维哈希-矩阵

一维哈希:
在这里插入图片描述
在 一 维 哈 希 中 , 我 们 是 将 长 度 长 度 为 n 的 序 列 哈 希 成 长 度 为 n 的 一 个 P 进 制 数 , 高 位 在 前 。 在一维哈希中,我们是将长度长度为n的序列哈希成长度为n的一个P进制数,高位在前。 nnP


二位哈希:
在这里插入图片描述
在 二 维 哈 希 中 , 就 是 将 n × m 的 序 列 哈 希 成 一 个 长 度 为 n × m 的 P 进 制 数 , 依 然 是 高 位 在 前 。 在二维哈希中,就是将n×m的序列哈希成一个长度为n×m的P进制数,依然是高位在前。 n×mn×mP

处理过程:

① 、 行 哈 希 : 首 先 对 矩 阵 的 每 一 行 的 m 个 元 素 分 别 进 行 一 维 哈 希 。 ①、行哈希:首先对矩阵的每一行的m个元素分别进行一维哈希。 m

② 、 列 哈 希 : 接 着 可 以 将 矩 阵 的 每 一 行 视 作 一 位 , 从 上 到 下 视 作 一 个 n 个 元 素 的 序 列 , 类 比 一 维 哈 希 。 ②、列哈希:接着可以将矩阵的每一行视作一位,从上到下视作一个n个元素的序列,类比一维哈希。 n

公式推导:

求大小为a×b的子矩阵的哈希值

① 、 首 先 预 处 理 整 个 n × m 的 矩 阵 每 一 行 的 哈 希 值 。 ①、首先预处理整个n×m的矩阵每一行的哈希值。 n×m

设 第 i 行 第 j 列 的 元 素 为 a [ i ] [ j ] , 1 < = i < = n , 1 < = j < = m , 设第i行第j列的元素为a[i][j],1<=i<=n,1<=j<=m, ija[i][j]1<=i<=n1<=j<=m

则 第 i 行 前 j 个 元 素 的 哈 希 值 h [ i ] [ j ] = h [ i ] [ j − 1 ] × P + a [ i ] [ j ] 。 则第i行前j个元素的哈希值h[i][j]=h[i][j-1]×P+a[i][j]。 ijh[i][j]=h[i][j1]×P+a[i][j]

② 、 再 求 a × b 的 矩 阵 的 哈 希 值 。 ②、再求a×b的矩阵的哈希值。 a×b
在这里插入图片描述

设 右 下 角 坐 标 为 ( i , j ) 的 a × b 的 矩 阵 的 哈 希 值 为 H [ i ] [ j ] , 矩 阵 每 一 行 的 b 个 元 素 的 哈 希 值 可 以 由 一 维 哈 希 的 方 法 求 出 为 h [ k ] [ j − b + 1 , j ] , k ∈ [ i − a + 1 , i ] 。 设右下角坐标为(i,j)的a×b的矩阵的哈希值为H[i][j],\\矩阵每一行的b个元素的哈希值可以由一维哈希的方法求出为h[k][j-b+1,j],k∈[i-a+1,i]。 (i,j)a×bH[i][j]bh[k][jb+1,j]k[ia+1,i]
在这里插入图片描述
则 其 对 应 的 第 i + 1 行 的 的 a × b 的 矩 阵 的 哈 希 值 H [ i + 1 ] [ j ] 可 以 由 该 矩 阵 的 所 有 元 素 向 高 位 移 动 b 位 , 再 加 上 第 i + 1 行 的 哈 希 值 , 然 后 减 去 第 i 个 矩 阵 的 第 一 行 的 哈 希 值 得 到 。 则其对应的第i+1行的的a×b的矩阵的哈希值H[i+1][j]可以由该矩阵的所有元素向高位移动b位,\\再加上第i+1行的哈希值,然后减去第i个矩阵的第一行的哈希值得到。 i+1a×bH[i+1][j]b,i+1i

即 : H [ i + 1 ] [ j ] = H [ i ] [ j ] × P b + h [ i + 1 ] [ j − b + 1 , j ] − h [ ( i + 1 ) − a ] [ j − b + 1 , j ] × P a b 。 要 注 意 , 第 i + 1 − a 行 的 元 素 要 比 第 i + 1 行 元 素 对 应 的 高 a × b 位 , 因 此 最 后 减 的 时 候 要 乘 上 。 即:H[i+1][j]=H[i][j]×P^b+h[i+1][j-b+1,j]-h[(i+1)-a][j-b+1,j]×P^{ab}。\\要注意,第i+1-a行的元素要比第i+1行元素对应的高a×b位,因此最后减的时候要乘上。 H[i+1][j]=H[i][j]×Pb+h[i+1][jb+1,j]h[(i+1)a][jb+1,j]×Pabi+1ai+1a×b


题目:

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

输入描述:
第一行四个整数M,N,A,B。
接下来一个M行N列的01矩阵,数字之间没有空格。
接下来一个整数Q。
接下来Q个A行B列的01矩阵,数字之间没有空格。

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

示例1:
输入
3 3 2 2
111
000
111
3
11
00
11
11
00
11

输出
1
0
1

数据范围:
A ≤ 100 , M , N ≤ 1000 , Q ≤ 1000 。 A≤100,M,N≤1000,Q≤1000。 A100M,N1000Q1000

具体落实:

① 、 预 处 理 分 别 计 算 每 一 行 的 哈 希 值 。 ② 、 根 据 递 推 关 系 计 算 n × m 的 矩 阵 中 , 所 有 a × b 的 子 矩 阵 的 哈 希 值 并 存 入 哈 希 表 中 。 ③ 、 计 算 输 入 的 子 矩 阵 的 哈 希 值 再 查 询 哈 希 表 。 ①、预处理分别计算每一行的哈希值。\\②、根据递推关系计算n×m的矩阵中,所有a×b的子矩阵的哈希值并存入哈希表中。\\③、计算输入的子矩阵的哈希值再查询哈希表。 n×ma×b


代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<unordered_set>
#define ull unsigned long long
using namespace std;
const int N=1010;
const int base=131;
int n,m,a,b;
ull h[N][N],p[N*N];
char str[N];

ull get(ull h[],int l,int r)
{
    return h[r]-h[l-1]*p[r-l+1];
}

int main()
{
    scanf("%d%d%d%d",&n,&m,&a,&b);

    for(int i=1;i<=n;i++)
    {
        scanf("%s",str+1);
        ///单独求每一行的哈希值
        for(int j=1;j<=m;j++)
            h[i][j]=h[i][j-1]*base+str[j]-'0';
    }

    p[0]=1;
    for(int i=1;i<=a*b;i++) p[i]=p[i-1]*base;

    unordered_set<ull> S;
    ///j枚举右端点,求所有a×b的子矩阵哈希值
    for(int j=b;j<=m;j++)
    {
        ull s=0;
        int l=j-b+1,r=j;
        for(int i=1;i<=n;i++)  ///按列求哈希
        {
            s=s*p[b]+get(h[i],l,r);
            if(i-a>0) s-=get(h[i-a],l,r)*p[a*b];
            if(i-a>=0) S.insert(s);
        }
    }

    int q;
    scanf("%d",&q);
    while(q--)
    {
        ///计算输入的子矩阵的值
        ull s=0;
        for(int i=1;i<=a;i++)
        {
            scanf("%s",str+1);
            for(int j=1;j<=b;j++)
                s=s*base+str[j]-'0';
        }
        if(S.count(s)) puts("1");
        else puts("0");
    }

    return 0;
}

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
二维模式匹配是指在一个文本矩阵中查找一个给定的模式矩阵的过程。这个问题可以被转化为在文本矩阵中寻找与模式矩阵值相同的子矩阵。这个过程可以通过将模式矩阵的哈值计算出来,然后在文本矩阵中计算每个可能的子矩阵的哈值进行匹配。 Rabin-Karp算法是一种基于哈的字符串匹配算法,它可以被推广到二维矩阵匹配中。在二维情况下,我们可以使用一个二维哈函数来计算矩阵的哈值。这个函数可以使用类似于Rabin-Karp算法中的哈函数,但需要对每一行进行哈,并将它们合并成一个矩阵的哈值。 具体来说,我们可以使用以下方法来计算二维矩阵的哈值: 1. 对于每一行,计算该行的哈值。 2. 将每一行的哈值合并成一个矩阵的哈值。 为了计算行的哈值,我们可以使用Rabin-Karp算法中的哈函数,计算每一行的哈值。为了计算矩阵的哈值,我们可以将每行的哈值合并成一个整体的哈值。具体来说,我们可以使用一个类似于Rabin-Karp算法中的滚动哈函数,将每一行的哈值合并成一个矩阵的哈值。 一旦我们计算出模式矩阵和文本矩阵的哈值,我们可以在文本矩阵中寻找与模式矩阵值相同的子矩阵。具体来说,我们可以在文本矩阵中滑动一个大小为模式矩阵的子矩阵的窗口,计算窗口中子矩阵的哈值,并将其与模式矩阵的哈值进行比较。如果它们相同,我们就找到了一个匹配。 需要注意的是,在计算哈值时,可能会出现哈冲突的情况。因此,在比较哈值时,我们需要使用一种方法来处理哈冲突。一种简单的方法是使用多个哈函数,每个哈函数都会产生一个哈值,只要有一个哈值匹配成功,我们就认为匹配成功。 总之,二维模式匹配可以通过使用二维哈函数和Rabin-Karp算法来实现。虽然这个算法的时间复杂度不是最优的,但是它具有非常好的实际应用效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值