字符串hash(二维)-poj3690
来源:互联网 发布:手机淘宝怎样修改星评 编辑:程序博客网 时间:2024/05/01 19:43
Description
The starry sky in the summer night is one of the most beautiful things on this planet. People imagine that some groups of stars in the sky form so-called constellations. Formally a constellation is a group of stars that are connected together to form a figure or picture. Some well-known constellations contain striking and familiar patterns of bright stars. Examples are Orion (containing a figure of a hunter), Leo (containing bright stars outlining the form of a lion), Scorpius (a scorpion), and Crux (a cross).
In this problem, you are to find occurrences of given constellations in a starry sky. For the sake of simplicity, the starry sky is given as a N × M matrix, each cell of which is a '*' or '0' indicating a star in the corresponding position or no star, respectively. Several constellations are given as a group of T P × Q matrices. You are to report how many constellations appear in the starry sky.
Note that a constellation appears in the sky if and only the corresponding P × Q matrix exactly matches some P × Q sub-matrix in the N × M matrix.
Input
The input consists of multiple test cases. Each test case starts with a line containing five integers N, M, T, P and Q(1 ≤ N, M ≤ 1000, 1 ≤ T ≤ 100, 1 ≤ P, Q ≤ 50).
The following N lines describe the N × M matrix, each of which contains M characters '*' or '0'.
The last part of the test case describe T constellations, each of which takes P lines in the same format as the matrix describing the sky. There is a blank line preceding each constellation.
The last test case is followed by a line containing five zeros.
Output
For each test case, print a line containing the test case number( beginning with 1) followed by the number of constellations appearing in the sky.
Sample Input
3 3 2 2 2*000***00**00*0**3 3 2 2 2*000***00**00*00*0 0 0 0 0
Sample Output
Case 1: 1Case 2: 2方法一:首先把一行看成一个字符串,计算出hash值,然后再把得到的hash值在列方向上看成字符串,计算hsah值代码如下:#include<iostream>#include<set>#include<map>#include<vector>#include<queue>#include<cmath>#include<climits>#include<cstdio>#include<string>#include<cstring>#include<algorithm>typedef long long LL;using namespace std;const int MAX=1110;const int MAX_T=110;const int B1=9973;const int B2=100000007;int N,M,T,P,Q;int loop=1;char field[MAX][MAX];char patterns[MAX_T][MAX][MAX];LL hash[MAX][MAX],tmp[MAX][MAX];void compute_hash(char a[][MAX],int n,int m){ LL t1=1; for(int i=0; i<Q; i++) t1*=B1; for(int i=0; i<n; i++) { LL e=0; for(int j=0; j<Q; j++) e=e*B1+a[i][j]; for(int j=0; j+Q<=m; j++) { tmp[i][j]=e; if(j+Q<m) e=e*B1-t1*a[i][j]+a[i][j+Q]; } } LL t2=1; for(int i=0; i<P; i++) t2*=B2; for(int i=0; i+Q<=m; i++) { LL e=0; for(int j=0; j<P; j++) e=e*B2+tmp[j][i]; for(int j=0; j+P<=n; j++) { hash[j][i]=e; if(j+P<n) e=e*B2-t2*tmp[j][i]+tmp[j+P][i]; } }}void solve(){ multiset<LL> uuseen; for(int i=0; i<T; i++) { compute_hash(patterns[i],P,Q); uuseen.insert(hash[0][0]); } compute_hash(field,N,M); for(int i=0; i+P<=N; i++) { for(int j=0; j+Q<=M; j++) uuseen.erase(hash[i][j]); } int ans=T-uuseen.size(); printf("Case %d: %d\n", loop++, ans);}int main(){ //freopen("in.txt","r",stdin); while(scanf("%d%d%d%d%d",&N,&M,&T,&P,&Q)!=EOF) { if(!P&&!Q&&!T&&!N&&!M) break; for(int i=0; i<N; i++) { scanf("%s",field[i]); } for(int i=0; i<T; i++) { for(int j=0; j<P; j++) { scanf("%s",patterns[i][j]); } } solve(); } return 0;}
方法2:位运算计算每一行的hash值,然后一行一行的匹配。
代码如下:#include <iostream>#include <algorithm>#include <cstring>#include <string>#include <cstdio>#include <cmath>#include <queue>#include <map>#include <set>#define MAXN 111111#define MAXM 555555#define INF 100000011#define lch(x) x<<1#define rch(x) x<<1|1#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define eps 1e-7using namespace std;long long h[1111][1111];int n, m, t, p, q;char mp[1111][1111], tmp[66];long long a[66];bool ok(){ for(int i = 0; i + p - 1 < n; i++) for(int j = q - 1; j < m; j++) { int flag = 1; for(int k = 0; k < p; k++) if(h[i + k][j] != a[k]) { flag = 0; break; } if(flag) return true; } return false;}int main(){ int cas = 0; while(scanf("%d %d %d %d %d", &n, &m, &t, &p, &q) != EOF) { if(!n && !m && !t && !q && !p) break; for(int i = 0; i < n; i++) scanf("%s", mp[i]); memset(h, 0, sizeof(h)); for(int i = 0; i < n; i++) for(int j = 0; j < q; j++) { if(mp[i][j] == '*') h[i][q - 1] |= (1LL << j); } for(int i = 0; i < n; i++) for(int j = q; j < m; j++) { if(mp[i][j - q] == '*') h[i][j] = h[i][j - 1] - 1LL; else h[i][j] = h[i][j - 1]; h[i][j] >>= 1LL; if(mp[i][j] == '*') h[i][j] |= (1LL << (q - 1)); } int cnt = 0; while(t--) { for(int i = 0; i < p; i++) { scanf("%s", tmp); a[i] = 0; for(int j = 0; j < q; j++) if(tmp[j] == '*') a[i] |= (1LL << j); } if(ok()) cnt++; } printf("Case %d: %d\n", ++cas, cnt); } return 0;}
- 字符串hash(二维)-poj3690
- poj3690 Constellations 字符串Hash
- URAL 1486(二维字符串hash)
- POJ 3690 字符串的二维hash
- URAL 1486 Equal Squares 二维字符串Hash + 邻接表分组
- HOJ 13383 The Big Painting 二维字符串hash
- poj2503(字符串hash)
- Tyvj1057(字符串hash)
- bzoj 2351: [BeiJing2011]Matrix(二维Hash)
- 哈希标记取代(KMP和AC自动机)poj3690
- poj3690 Constellations
- poj 1200(字符串hash)
- hdu4821 字符串 hash (bkdrhash)
- UVAL 4513 (字符串Hash)
- poj 2503(字符串hash)
- POJ 2418(字符串HASH)
- bzoj3555(字符串hash,疑问??)
- 算法随笔(字符串hash)
- 【discuzx3】discuzx2升级到discuzx3步骤
- Java IO----RandomAccessFile
- 新站如何让百度快速收录
- 收藏夹
- iis加载不到php.ini
- 字符串hash(二维)-poj3690
- 13个mysql数据库的实用SQL小技巧
- 如何解决SVN Commit failed (details follow): Access denied
- java求阶乘和,n的重要性,犯了致命错误。
- 记录一下PHP数组数据分页的方法 array_slice() 函数的使用
- C程序语言strstr函数分析和使用
- 关于程序用途的小见解
- HDU 3377 Plan 解题报告(插头DP)
- java读取配置文件里的信息