poj3690 Constellations
2017-12-31 20:45
239 查看
Constellations
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
Sample Output
Source
2008 Asia Hefei Regional Contest Online by USTC
题目大意:给一个n*m的矩阵,再给T个p*q的小矩阵,问有多少个小矩阵在大矩阵中出现了.
分析:get到了不少技巧啊.
一开始的思路肯定是AC自动机,但是矩阵与矩阵之间匹配明显不好搞,果断放弃.然后很容易就能想到hash.对于大矩阵的每一个p*q的子矩阵的hash值存入一个数据结构中,然后对每个小矩阵的hash值看看有多少个已经存在了就可以了.那么如何求hash呢?
二维hash+滚动hash.先推出每一行上连续q个的hash,第i位结尾的hash值可以从第i-1位结尾的推导过来.接下来处理每一列的都可以了.为了避免mod一个数,采用了自然溢出的处理方法.在unsigned long long类型上处理. 最后将所有的hash值放到hash表上处理,利用链表防止冲突.
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 6522 | Accepted: 1311 |
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 *00 0** *00 ** 00 *0 ** 3 3 2 2 2 *00 0** *00 ** 00 *0 0* 0 0 0 0 0
Sample Output
Case 1: 1 Case 2: 2
Source
2008 Asia Hefei Regional Contest Online by USTC
题目大意:给一个n*m的矩阵,再给T个p*q的小矩阵,问有多少个小矩阵在大矩阵中出现了.
分析:get到了不少技巧啊.
一开始的思路肯定是AC自动机,但是矩阵与矩阵之间匹配明显不好搞,果断放弃.然后很容易就能想到hash.对于大矩阵的每一个p*q的子矩阵的hash值存入一个数据结构中,然后对每个小矩阵的hash值看看有多少个已经存在了就可以了.那么如何求hash呢?
二维hash+滚动hash.先推出每一行上连续q个的hash,第i位结尾的hash值可以从第i-1位结尾的推导过来.接下来处理每一列的都可以了.为了避免mod一个数,采用了自然溢出的处理方法.在unsigned long long类型上处理. 最后将所有的hash值放到hash表上处理,利用链表防止冲突.
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <map> #include <set> using namespace std; typedef unsigned long long ull; const ull mod1 = 9973,mod2 = 1e8+7,mod3 = 999987; int n,m,t,p,q,cas; ull has[1010][1010],has2[1010][1010],jie1[1010],jie2[1010],num[1010 * 1010],w[1010 * 1010],to[1010 * 1010],nextt[1010 * 1010],head[1010 * 1010],tot = 1; char s[1010][1010],s2[110][55][55]; void get() { for (int i = 1; i <= n; i++) { for (int j = 1; j <= q; j++) { if (j == 1) has[i][j] = s[i][j]; else has[i][j] = (has[i][j - 1] * mod1 + s[i][j]); } for (int j = q + 1; j <= m; j++) has[i][j] = has[i][j - 1] * mod1 - s[i][j - q] * jie1[q] + s[i][j]; } for (int j = 1; j <= m; j++) { for (int i = 1; i <= p; i++) { if (i == 1) has2[i][j] = has[i][j]; else has2[i][j] = has2[i - 1][j] * mod2 + has[i][j]; } for (int i = p + 1; i <= n; i++) has2[i][j] = has2[i - 1][j] * mod2 - has[i - p][j] * jie2[p] + has[i][j]; } } void get2(int x) { for (int i = 1; i <= p; i++) { for (int j = 1; j <= q; j++) { if (j == 1) has[i][j] = s2[x][i][j]; else has[i][j] = (has[i][j - 1] * mod1 + s2[x][i][j]); } } for (int j = 1; j <= q; j++) { for (int i = 1; i <= p; i++) { if (i == 1) has2[i][j] = has[i][j]; else has2[i][j] = has2[i - 1][j] * mod2 + has[i][j]; } } } void add(ull x) { int h = x % mod3; for (int i = head[h]; i; i = nextt[i]) { if (w[i] == x) return; } w[tot] = x; num[tot] = 1; nextt[tot] = head[h]; head[h] = tot++; } int query(ull x) { int h = x % mod3; for (int i = head[h]; i; i = nextt[i]) if (w[i] == x) return num[i]; return 0; } int solve() { int res = 0; get(); for (int i = p; i <= n; i++) for (int j = q; j <= m; j++) add(has2[i][j]); for (int i = 1; i <= t; i++) { get2(i); res += query(has2[p][q]); } return res; } int main() { jie1[0] = jie2[0] = 1; for (int i = 1; i <= 1000; i++) { jie1[i] = jie1[i - 1] * mod1; jie2[i] = jie2[i - 1] * mod2; } while (scanf("%d%d%d%d%d",&n,&m,&t,&p,&q) != EOF && n + m + t + p + q) { memset(head,0,sizeof(head)); tot = 1; memset(num,0,sizeof(num)); for (int i = 1; i <= n; i++) scanf("%s",s[i] + 1); for (int i = 1; i <= t; i++) for (int j = 1; j <= p; j++) scanf("%s",s2[i][j] + 1); printf("Case %d: %d\n",++cas,solve()); } return 0; }
相关文章推荐
- POJ 3690 Constellations (哈希)
- POJ 3690(Constellations-矩阵hash)
- poj 3690 Constellations 二维滚动哈希匹配
- POJ 3690 Constellations 简单hash
- poj 3690 Constellations
- POJ 3690 Constellations 笔记
- [poj] 3690 Constellations || 矩阵hash
- POJ 3690 Constellations 哈希表 矩阵匹配
- POJ 3690 Constellations + Gym - 100783J The Big Painting 二维字符串hash
- poj 3690 Constellations 矩阵的hash
- POJ3690 Constellations 【KMP】
- POJ 3690 Constellations(二进制压位+KMP)
- poj3690——Kindergarten(最大独立点集,匈牙利算法)
- POJ 3690 Intervals 费用流 最大变最小
- poj 3690 字符矩阵匹配----HASH算法
- POJ 3690 Constellations hash
- POJ3690+位运算
- POJ3690+位运算
- poj 3690(二维哈希)
- POJ 2049 Finding Nemo