【BZOJ 2462】矩阵模板 (二维哈希)
2017-09-08 23:00
453 查看
题目
给定一个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 ; static int ha[][]=new int ; static int p1[]=new int ; static int p2[]=new int ; 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 BeiJing 2011 矩阵模板 二维hash
- [BZOJ2462] [BeiJing2011]矩阵模板(二维Hash)
- BZOJ 2462 BeiJing 2011 矩阵模板 二维hash
- [BZOJ]2462: [BeiJing2011]矩阵模板 二维hash
- BZOJ.2462.[BeiJing2011]矩阵模板(二维Hash)
- BZOJ2462[Beijing2011]矩阵模板(二维Hash)
- bzoj2462 [BeiJing2011]矩阵模板 hash
- BZOJ 2462: [BeiJing2011]矩阵模板
- [BZOJ2462]矩阵模板(暴力||矩阵hash)
- BZOJ 2462: [BeiJing2011]矩阵模板
- [bzoj2462] [BeiJing2011]矩阵模板
- BZOJ 2462: [BeiJing2011]矩阵模板
- 【kmp算法】【Rabin-Karp算法】bzoj2462 [BeiJing2011]矩阵模板
- bzoj 2462 [BeiJing2011]矩阵模板
- BZOJ 2462: [BeiJing2011]矩阵模板 二维哈希
- 【BeiJing2011】【BZOJ2462】矩阵模板
- [BZOJ 2462 BeiJing2011矩阵模板]矩阵Hash
- 【bzoj2462】[BeiJing2011]矩阵模板
- BZOJ 2462/2351 [BeiJing2011]矩阵模板/[BeiJing2011]Matrix 二维哈希
- bzoj 2462 [BeiJing2011]矩阵模板 (hash)