题意

给定一个 \(n\times m\) 的矩阵,在给定一个 \(x\times y\) 的小矩阵,求小矩阵在大矩阵中出现的次数。

\(1 \leq n,m \leq 1000\)

\(1\leq x,y \leq 100\)

思路

做法比较显然,先对大矩阵哈希,在每个位上确定一个“位权”,\(Base^k\) ,对于矩阵的 \((x,y)\) 位置,可以令 \(k=(x-1)*m+y-1\) ,然后求二维前缀和。接下来把小矩阵放在大矩阵的 \((1,1)(x,y)\) 位置哈希,将哈希值进行比较。接下来考虑的就是移动矩阵哈希值的变化,不难发现,因为 \((1,1)\) 的位权是 \(1\) ,所以移动到哪里,哈希值就乘上那里的位权即可。

关于哈希的基数和模数的取值,首先基数 \(Base\) 要大于不同元素的个数,模数尽量取大质数,最好是孪生的,但注意 \(1e9+7,1e9+9\) 由于太大众,不免会被卡,我个人习惯再取一个 \(19260817\) 。然后 \(101111,101113,101117,101119\) 也是挺好记的质数,在用链式哈希表的时候可以当一维数组下标。

代码

#include<bits/stdc++.h>
#define FOR(i,x,y) for(int i=(x),i##END=(y);i<=i##END;++i)
#define DOR(i,x,y) for(int i=(x),i##END=(y);i>=i##END;--i)
typedef long long LL;
using namespace std;
const int Base[3]={29,31,37};
const int Mod[3]={(int)1e9+7,(int)1e9+9,1926081};
const int N=1005;
char A[N][N],B[N][N];
LL pB[3][N*N];
LL s[3][N][N],h[3];
int n,m,p,q;
inline int Hs(int x,int y){return (x-1)*m+y-1;} LL S(int k,int X1,int Y1,int X2,int Y2)
{
return (
(s[k][X2][Y2]-s[k][X1-1][Y2]-s[k][X2][Y1-1]+s[k][X1-1][Y1-1])
%Mod[k]+Mod[k]
)%Mod[k];
} int main()
{
FOR(k,0,2){pB[k][0]=1;FOR(i,1,N*N-1)pB[k][i]=pB[k][i-1]*Base[k]%Mod[k];}
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
FOR(i,1,n)scanf("%s",A[i]+1);
scanf("%d%d",&p,&q);
FOR(i,1,p)scanf("%s",B[i]+1);
if(p>n||q>m){puts("0");continue;} FOR(k,0,2)FOR(i,1,n)FOR(j,1,m)
s[k][i][j]=(
(s[k][i][j-1]+s[k][i-1][j]-s[k][i-1][j-1]+(A[i][j]-'a'+1)*pB[k][Hs(i,j)])
%Mod[k]+Mod[k]
)%Mod[k];
FOR(k,0,2)
{
h[k]=0;
FOR(i,1,p)FOR(j,1,q)h[k]=(h[k]+(B[i][j]-'a'+1)*pB[k][Hs(i,j)])%Mod[k];
} int cnt=0;
FOR(i,1,n-p+1)FOR(j,1,n-q+1)
{
bool flag=1;
FOR(k,0,2)if(
h[k]*pB[k][Hs(i,j)]%Mod[k]!=S(k,i,j,i+p-1,j+q-1)
)flag=0;
if(flag)cnt++;
}
printf("%d\n",cnt);
}
return 0;
}

UVA 11019 Matrix Matcher(哈希)的更多相关文章

  1. UVA 11019 Matrix Matcher 矩阵匹配器 AC自动机 二维文本串查找二维模式串

    链接:https://vjudge.net/problem/UVA-11019lrjP218 matrix matcher #include<bits/stdc++.h> using na ...

  2. UVA - 11019 Matrix Matcher (二维字符串哈希)

    给你一个n*m的矩阵,和一个x*y的模式矩阵,求模式矩阵在原矩阵中的出现次数. 看上去是kmp在二维情况下的版本,但单纯的kmp已经无法做到了,所以考虑字符串哈希. 类比一维情况下的哈希算法,利用容斥 ...

  3. UVa 11019 Matrix Matcher - Hash

    题目传送门 快速的vjudge传送门 快速的UVa传送门 题目大意 给定两个矩阵S和T,问T在S中出现了多少次. 不会AC自动机做法. 考虑一维的字符串Hash怎么做. 对于一个长度为$l$的字符串$ ...

  4. UVA 11019 Matrix Matcher(ac自动机)

    题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  5. AC自动机(二维) UVA 11019 Matrix Matcher

    题目传送门 题意:训练指南P218 分析:一行一行的插入,一行一行的匹配,当匹配成功时将对应子矩阵的左上角位置cnt[r][c]++;然后统计 cnt[r][c] == x 的数量 #include ...

  6. uva 11019 Matrix Matcher

    题意:给出一个n*m的字符矩阵T,你的任务是找出给定的x*y的字符矩阵P在T中出现了多少次. 思路:要想整个矩阵匹配,至少各行都得匹配.所以先把P的每行看做一个模式串构造出AC自动机,然后在T中的各行 ...

  7. UVA 11019 Matrix Matcher(二维hash + 尺取)题解

    题意:在n*m方格中找有几个x*y矩阵. 思路:二维hash,总体思路和一维差不太多,先把每行hash,变成一维的数组,再对这个一维数组hash变成二维hash.之前还在想怎么快速把一个矩阵的hash ...

  8. UVA - 11019 Matrix Matcher hash+KMP

    题目链接:传送门 题解: 枚举每一行,每一行当中连续的y个我们hash 出来 那么一行就是 m - y + 1个hash值,形成的一个新 矩阵 大小是 n*(m - y + 1), 我们要找到x*y这 ...

  9. UVA 11019 Matrix Matcher ( 二维字符串匹配, AC自动机 || 二维Hash )

    题目: 传送门 题意: 给你一个 n * m 的文本串 T, 再给你一个 r * c 的模式串 S: 问模式串 S 在文本串 T 中出现了多少次. 解: 法一: AC自动机 (正解) 670ms 把模 ...

随机推荐

  1. C# WPF Halcon HDevEngine混合编程

    1. WPF+Halcon 引用halcondotnet.dll和hdevenginedotnet.dll XAML中导入命名空间xmlns:halcon=”clr-namespace:HalconD ...

  2. request.getServletPath(),request.getContextPath()

    2018-11-24  16:34:33 1. getServletPath():获取能够与“url-pattern”中匹配的路径,注意是完全匹配的部分,*的部分不包括. 2. getPageInfo ...

  3. 使用JFileChooser实现在指定文件夹下批量添加根据“数字型样式”或“非数字型样式”命令的文件夹

    2018-11-05 20:57:00开始写 Folder.java类 import javax.swing.JFrame; import javax.swing.JPanel; import jav ...

  4. mysql 对表字段进行长度截取操作

    现在的问题是数据库某一个表中其中的车牌号字段有些数据多了一位,需要把它找出来然后把多的最后一位去掉..... 通过自带的length(字段名)函数把长度过长的数据过滤出来,其中,一个汉字算3个字符,一 ...

  5. MVC中的Ajax与增删改查(二)

    上一篇记录的是前台操作,下面写一下后台 ,本来自认为是没有必要做补充,毕竟思路啥的都有,实际上在做删除操作的时候,折腾了一天,还是自己太嫩,逻辑不够严谨,这里作下记录. 关于表结构这里再作下说明: ① ...

  6. 了解一下UTF-16

    1)先啰嗦一下 UTF-16是一种编码格式.啥是编码格式?就是怎么存储,也就是存储的方式. 存储啥?存二进制数字.为啥要存二进制数字? 因为Unicode字符集里面把二进制数字和字符一一对应了,存二进 ...

  7. Linux基础命令---检查密码文件pwck

    pwck 检查用户密码文件“/etc/passwd”和“/etc/shadow”的完整性,将验证结果送到标砖输出.提示用户删除格式不正确或有其他不可更正错误的条目.检查以验证每个条目是否具有:正确的字 ...

  8. php 网站301重定向设置代码实战案例

    php 网站301重定向设置代码实战案例 301重定向就是页面永久性移走的意思,搜索引擎知道这个页面是301重定向的话,就会把旧的地址替换成重定向之后的地址. 302重定向就是页面暂时性转移,搜索引擎 ...

  9. Oracle执行计划 explain plan

    Rowid的概念:rowid是一个伪列,既然是伪列,那么这个列就不是用户定义,而是系统自己给加上的. 对每个表都有一个rowid的伪列,但是表中并不物理存储ROWID列的值.不过你可以像使用其它列那样 ...

  10. 每日linux命令学习-head命令和tail命令

    本节主要学习了linux文件浏览的相关命令,包括cat.less.more.read.tail等,由于本人经常使用cat.less.more命令,已经较为熟悉,所以本节重点学习head命令和tail命 ...