poj3690 Constellations
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 6522 | Accepted: 1311 |
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 *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
#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; }