题目


给定一个M行N列的01矩阵,以及Q个A行B列的01矩阵,你需要求出这Q个矩阵哪些在

原矩阵中出现过。

所谓01矩阵,就是矩阵中所有元素不是0就是1。

输入


输入文件的第一行为M、N、A、B,参见题目描述。

接下来M行,每行N个字符,非0即1,描述原矩阵。

接下来一行为你要处理的询问数Q。

接下来Q个矩阵,一共Q*A行,每行B个字符,描述Q个01矩阵。

输出


你需要输出Q行,每行为0或者1,表示这个矩阵是否出现过,0表示没有出现过,1表

示出现过。

样例输入

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

样例输出

1
0
1

题解

二维哈希即使先把一列哈希成一个数字,那么二维数组就变为一维数组了,那么再对这个一维数组哈希,就得到了一个二维数组的哈希值。

如何迅速算出\(n \times m\)矩阵的所有\(a \times b\)子矩阵的哈希值?

利用滚动哈希,可以吧滚动哈希看成是以哈希种子(一个素数)为进位的数字,那么我们只要预处理出这个进位下每一位的数值,就可以很快减去之前的前缀,类似与1100去掉最前面的1000,只要减去即可。对于二维数组,也是只要减去之前的方块即可(画个图就能理解了)。

import java.io.*;
import java.util.*; public class Main {
static final int N = (int)1e3+10;
static char s[][]=new char[N][N];
static int ha[][]=new int[N][N];
static int p1[]=new int[N];
static int p2[]=new int[N];
static int hash[]=new int[N*N];
static int seed1=123,seed2=1789;
public static void main(String[] args) {
InputStream sysi = System.in;
OutputStream syso = System.out;
InputReader in = new InputReader(sysi);
PrintWriter out = new PrintWriter(syso);
int n=in.nextInt(),m=in.nextInt(),
a=in.nextInt(),b=in.nextInt();
for(int i=0;i<n;i++) s[i]=in.next().toCharArray();
for(int i=0;i<n;i++) {
for(int j=0;j<m;j++) {
ha[i+1][j+1]=ha[i+1][j]*seed1+s[i][j];
}
}
for(int i=0;i<n;i++) {
for(int j=0;j<m;j++) {
ha[i+1][j+1]+=ha[i][j+1]*seed2;
}
}
p1[0]=p2[0]=1;
for(int i=1;i<=n;i++) p1[i]=p1[i-1]*seed2;
for(int i=1;i<=m;i++) p2[i]=p2[i-1]*seed1;
int tot=0;
for(int i=a;i<=n;i++) {
for(int j=b;j<=n;j++) {
int x=ha[i][j]-ha[i-a][j]*p1[a]-ha[i][j-b]*p2[b]+ha[i-a][j-b]*p1[a]*p2[b];
hash[tot++]=x;
}
}
Arrays.sort(hash,0,tot);
int q=in.nextInt(),x;
while(q--!=0) {
for(int i=0;i<a;i++) s[i]=in.next().toCharArray();
for(int i=0;i<a;i++) {
for(int j=0;j<b;j++) {
ha[i+1][j+1]=ha[i+1][j]*seed1+s[i][j];
}
}
for(int i=0;i<a;i++) {
for(int j=0;j<b;j++) {
ha[i+1][j+1]+=ha[i][j+1]*seed2;
}
}
x=ha[a][b];
int l=0,r=tot-1,ans=-1;
while(l<=r) {
int mid=(l+r)>>1;
if(hash[mid]==x) {
ans=mid;break;
}
if(hash[mid]<x) l=mid+1;
else r=mid-1;
}
if(ans==-1) out.println("0");
else out.println("1");
}
out.flush();
out.close();
} static class InputReader {
public BufferedReader reader;
public StringTokenizer tokenizer; public InputReader(InputStream stream) {
reader = new BufferedReader(new InputStreamReader(stream), 32768);
tokenizer = null;
} public String next() {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
try {
tokenizer = new StringTokenizer(reader.readLine());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return tokenizer.nextToken();
} public int nextInt() {
return Integer.parseInt(next());
}
}

【BZOJ 2462】矩阵模板 (二维哈希)的更多相关文章

  1. BZOJ 2462 矩阵模板(二维hash)

    题意:给出一个n*m的01矩阵,以及k个a*b的01矩阵,问每个是否能匹配原来的01矩阵. 由于k个矩阵的长和宽都是一样的,所以把原矩阵的所有a*b的子矩阵给hash出来.然后依次查找是否存在即可. ...

  2. BZOJ.2462.[BeiJing2011]矩阵模板(二维Hash)

    题目链接 序列上的Hash和前缀和差不多,二维Hash也和二维前缀和差不多了. 预处理大矩阵所有r*c的小矩阵hash值,再对询问的矩阵Hash. 类比于序列上\(s[r]-s[l-1]*pow[r- ...

  3. BZOJ2462[Beijing2011]矩阵模板(二维Hash)

    二维矩阵匹配问题,至今不知道Q的范围是多少,反正是要求做到读入复杂度. 二维Hash:就是一维的等效拓展,注意两维的Base不能相同. 其余就是一维Hash和二维前缀和的结合,可以自然溢出,据说概率很 ...

  4. bzoj 2351 [BeiJing2011]Matrix——二维哈希

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2351 就是先把每行单独从左到右扫着乘一个 b1 哈希起来,然后再按列从上往下乘一个 b2 哈 ...

  5. AcWing - 156 矩阵(二维哈希)

    题目链接:矩阵 题意:给定一个$m$行$n$列的$01$矩阵$($只包含数字$0$或$1$的矩阵$)$,再执行$q$次询问,每次询问给出一个$a$行$b$列的$01$矩阵,求该矩阵是否在原矩阵中出现过 ...

  6. 依据矩阵的二维相关系数进行OCR识别

    我想通过简单的模板匹配来进行图像识别. 把预处理好的字符图片,分别与A到Z的样本图片进行模板匹配. 结果最大的表明相关性最大,就能够识别字符图片了. 在实际应用中.我用了openCV的matchTem ...

  7. Luogu P2742 模板-二维凸包

    Luogu P2742 模板-二维凸包 之前写的实在是太蠢了.于是重新写了一个. 用 \(Graham\) 算法求凸包. 注意两个向量 \(a\times b>0\) 的意义是 \(b\) 在 ...

  8. URAL - 1486 Equal Squares 二维哈希+二分

    During a discussion of problems at the Petrozavodsk Training Camp, Vova and Sasha argued about who o ...

  9. 牛客练习赛1 矩阵 字符串二维hash+二分

    题目 https://ac.nowcoder.com/acm/contest/2?&headNav=www#question 解析 我们对矩阵进行二维hash,所以每个子矩阵都有一个额hash ...

随机推荐

  1. python之迷宫BFS

    # @File: maze_queue_bfs from collections import deque maze = [ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0 ...

  2. MySQL GTID复制

    什么是GTID 什么是GTID呢, 简而言之,就是全局事务ID(global transaction identifier ),最初由google实现,官方MySQL在5.6才加入该功能.GTID是事 ...

  3. python_13(前端—cs)

    第1章 前端三大标准:1.1 三大标准介绍 1.2 html标签一览表 第2章 结构标准 html 2.1 html结构 2.2 html常用标签 2.2.1 h1-h6 2.2.2 span 2.2 ...

  4. AJPFX总结内部类

    内部类:内部类的访问规则:1. 内部类可以直接访问外部类中的成员,包括私有   原因是内部类中持有了一个外部类的引用,格式:外部类.this2. 外部类要访问内部类,必须建立内部类对象访问格式:1.  ...

  5. 关于ES6的Promise的使用深入理解

    ES6的promise对象研究 什么叫promise? Promise对象可以理解为一次执行的异步操作,使用promise对象之后可以使用一种链式调用的方式来组织代码:让代码更加的直观. 那我们为什么 ...

  6. 边框圆角值的问题、white-space、word-wrap、margin对布局的影响

    1.边框圆角(border-radius)值的问题 border-radius : 7px 7px 7px 0; 四个值的顺序是左上.右上.右下.左下 2.white-space 规定段落中的文本不换 ...

  7. css实现行内文字垂直居中

    之前本人一直使用浮动.相对定位.绝对定位和display:table等css的方法进行定位.网上得知flex可实现弹性布局,符合未来发展趋势,随尝试. 1:让盒子行内文字垂直居中,解决思路是讲文字的行 ...

  8. android动画之android:interpolator属性使用

    android动画之android:interpolator使用 Interpolator 被用来修饰动画效果,定义动画的变化率,可以使存在的动画效果accelerated(加速),decelerat ...

  9. Eclipse项目转Android Studio

    刚来某公司的时候,发现Android开发仍然还在使用Eclipse,编码无规范,渠道打包竟然手动,svn版本主干分支管理混乱,总之各种low... 对于有强迫症的我来说,属实不可忍.但无奈,新人一个, ...

  10. (转)Synopsys工具简介

    DC Ultra--Design Compiler的最高版本 在Synopsys软件中完整的综合方案的核心是DC UltraTM,对所有设计而言它也是最好级别的综合平台.DC Ultra添加了全面的数 ...