【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 ...
随机推荐
- 2019 年 Vue 学习路线图!
如果你是 Vue 开发新手,可能已经听过很多行话术语,比如单页面应用程序.异步组件.服务器端渲染,等等.你可能还听说过与 Vue 有关的一些工具和库,比如 Vuex.Webpack.Vue CLI 和 ...
- 浅谈web前端性能优化
前端性能优化: 一.尽可能减少前端http请求. 1.合并优化脚本文件和css文件. 2.同种类型的背景图片尽量放在一起,用css控制显示. 二.使用浏览器缓存. 如果能强制浏览器缓存在本地,将会降低 ...
- UESTC - 878 温泉旅店 二维费用背包问题
http://acm.uestc.edu.cn/#/problem/show/878 设dp[i][j][k]表示在前i个数中,第一个得到的异或值是j,第二个人得到的异或值是k的方案数有多少种. 因为 ...
- Hadoop体系结构管理
一.查看Zookeeper信息 [hadoop@weekend01 ~]$zkServer.sh status JMX enabled by default Using config: /hadoop ...
- 爬虫中动态的POST参数
爬虫的过程中,有的网站提交POST数据时候每次都会带上不懂POST参数,要想爬到数据首先的知道怎么构造这些动态的参数. 1.分析提交POST数据的最原始网页,分析原始网页的源代码,查找里面是否包含有你 ...
- 拦截@RequestBody的请求数据
要拦截首先想到的是拦截器,@RequestBody只能以流的方式读取,流被读过一次后,就不在存在了,会导致会续无法处理,因此不能直接读流 为了解决这个问题,思路如下: 1.读取流前先把流保存一下 2. ...
- intellij idea 调试 lua程序, 突然崩溃或者xmx不够的情况
将内存各方面的数值都改大一点.都什么时代了,默认数值还这么低... -server-Xms256m-Xmx1024m-XX:ReservedCodeCacheSize=240m-XX:+UseConc ...
- iOS 根据屏幕宽度, 高度判断手机设备
#define iPhone_5 [UIScreen mainScreen].bounds.size.width == 320.0 #define iPhone_6 [UIScreen mainScr ...
- 不全屏显示、手柄不居中的SlidingDrawer
SlidingDrawer是一个滑动式抽屉,通过点击或拖拽手柄(handle)来显示或隐藏内容(content). 看了很多关于SlidingDrawer的例子,但基本都是全屏显示,并且手柄居中的.我 ...
- 解决jenkins插件列表为空的问题
可能是由于Jenkins的更新网站被QIANG,因此,请使用 http://mirror.xmission.com/jenkins/updates/update-center.json 来进行更新