【BZOJ 2462】矩阵模板 (二维哈希)
题目
给定一个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】矩阵模板 (二维哈希)的更多相关文章
- BZOJ 2462 矩阵模板(二维hash)
题意:给出一个n*m的01矩阵,以及k个a*b的01矩阵,问每个是否能匹配原来的01矩阵. 由于k个矩阵的长和宽都是一样的,所以把原矩阵的所有a*b的子矩阵给hash出来.然后依次查找是否存在即可. ...
- BZOJ.2462.[BeiJing2011]矩阵模板(二维Hash)
题目链接 序列上的Hash和前缀和差不多,二维Hash也和二维前缀和差不多了. 预处理大矩阵所有r*c的小矩阵hash值,再对询问的矩阵Hash. 类比于序列上\(s[r]-s[l-1]*pow[r- ...
- BZOJ2462[Beijing2011]矩阵模板(二维Hash)
二维矩阵匹配问题,至今不知道Q的范围是多少,反正是要求做到读入复杂度. 二维Hash:就是一维的等效拓展,注意两维的Base不能相同. 其余就是一维Hash和二维前缀和的结合,可以自然溢出,据说概率很 ...
- bzoj 2351 [BeiJing2011]Matrix——二维哈希
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2351 就是先把每行单独从左到右扫着乘一个 b1 哈希起来,然后再按列从上往下乘一个 b2 哈 ...
- AcWing - 156 矩阵(二维哈希)
题目链接:矩阵 题意:给定一个$m$行$n$列的$01$矩阵$($只包含数字$0$或$1$的矩阵$)$,再执行$q$次询问,每次询问给出一个$a$行$b$列的$01$矩阵,求该矩阵是否在原矩阵中出现过 ...
- 依据矩阵的二维相关系数进行OCR识别
我想通过简单的模板匹配来进行图像识别. 把预处理好的字符图片,分别与A到Z的样本图片进行模板匹配. 结果最大的表明相关性最大,就能够识别字符图片了. 在实际应用中.我用了openCV的matchTem ...
- Luogu P2742 模板-二维凸包
Luogu P2742 模板-二维凸包 之前写的实在是太蠢了.于是重新写了一个. 用 \(Graham\) 算法求凸包. 注意两个向量 \(a\times b>0\) 的意义是 \(b\) 在 ...
- URAL - 1486 Equal Squares 二维哈希+二分
During a discussion of problems at the Petrozavodsk Training Camp, Vova and Sasha argued about who o ...
- 牛客练习赛1 矩阵 字符串二维hash+二分
题目 https://ac.nowcoder.com/acm/contest/2?&headNav=www#question 解析 我们对矩阵进行二维hash,所以每个子矩阵都有一个额hash ...
随机推荐
- CentOS7下如何正确安装并启动Docker(图文详解)
我使用了CentOS 7操作系统,可以非常容易地安装Docker环境.假设,下面我们都是用root用户进行操作,执行如下命令进行准备工作: yum install -y yum-utils yum-c ...
- hdu1811 Rank of Tetris 并查集+拓扑排序
#include <stdio.h> #include <string.h> #include <vector> #include <queue> us ...
- Java | 基础归纳 | Gson && Json
JSON: JSON就是一种数据的组织形式,用于数据传输. 地址:https://mvnrepository.com/artifact/net.sf.json-lib/json-lib/2.4 Mav ...
- 回文树1960. Palindromes and Super Abilities
Bryce1010模板 http://acm.timus.ru/problem.aspx?space=1&num=1960 #include <bits/stdc++.h> usi ...
- subline应用之常用插件
汉化插件:ChineseLocalzations IMESupport插件:解决软件输入法跟随问题 SublimeREPL插件:可以用于运行和调试一些需要交互的程序如python SublimeCod ...
- Suricata的命令行解释
见官网 https://suricata.readthedocs.io/en/latest/command-line-options.html root@SELKS:~# suricata Suric ...
- spark序列化及MapOutputTracker解析
本文主要打算对spark内部的序列化机制以及在shuffle map中起衔接作用的MapOutputTracker做一下剖析.主要涉及具体实现原理以及宏观设计的一些思路. 1,spark序列化 任何一 ...
- php使用json_decode返回NULL
php5.2以后自带json_decode函数,但是对json文本串的格式要求非常严格. 很可能使用该函数得到的返回值是NULL 可以使用使用json_last_error()函数获取到的返回值来帮助 ...
- [转]MVC 检测用户是否已经登录
本文转自:http://blog.csdn.net/jayzai/article/details/41252137 当我们访问某个网站的时候需要检测用户是否已经登录(通过Session是否为null) ...
- SSM-WebMVC(三)
SSM-WebMVC(三) 一.Annotated Controllers 应用程序控制器 handlerMethod(处理方法) ㈠方法入参 (springmvc针对于在controller ...