Constellations
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 6822 | Accepted: 1382 |
题目链接:http://poj.org/problem?id=3690
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
题意:
给出一个n*m个矩阵,并且给出若干个p*q的小矩阵,然后回答有多少个小矩阵在大矩阵中出现了的。
题解:
数据范围不是很大,直接二维暴力hash就是了。
二维hash跟一维都差不多的吧,具体细节见代码吧。
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <set> using namespace std; typedef long long ll; typedef unsigned int Ull ; const int N = 2005; int n, m, T, p, q; Ull x1 = 1413, x2 = 12582917; Ull px1[N], px2[N]; Ull Hash[N][N], Hash_Table[N * N], val[55][55]; char s[N][N], t[N][N]; int main() { px1[0] = px2[0] = 1; for(int i = 1; i <= 2000; i++) { px1[i] = px1[i - 1] * x1; px2[i] = px2[i - 1] * x2; } int cnt = 0; while(scanf("%d%d%d%d%d", &n, &m, &T, &p, &q) != EOF) { if(n + m + T + p + q <= 0) break ; cnt++; memset(Hash,0,sizeof(Hash)); for(int i = 1; i <= n; i++) { scanf("%s", s[i] + 1); for(int j = 1; j <= m; j++) { Hash[i][j] = Hash[i][j - 1] * x1 + (Ull)s[i][j]; } } for(int j = 1; j <= m; j++) { for(int i = 1; i <= n; i++) { Hash[i][j] = Hash[i - 1][j] * x2 + Hash[i][j]; } } int tt = T; multiset<Ull> S; while(tt--) { memset(val,0,sizeof(val)); for(int i = 1; i <= p; i++) { scanf("%s", t[i] + 1); for(int j = 1; j <= q; j++) { val[i][j] = val[i][j - 1] * x1 + (Ull)t[i][j]; } } for(int j = 1; j <= q; j++) { for(int i = 1; i <= p; i++) { val[i][j] = val[i - 1][j] * x2 + val[i][j]; } } S.insert(val[p][q]); } for(int i = p; i <= n; i++) { for(int j = q; j <= m; j++) { Ull Val = Hash[i][j] + Hash[i - p][j - q] * px1[q] * px2[p] - Hash[i][j - q] * px1[q] - Hash[i - p][j] * px2[p]; S.erase(Val); } } printf("Case %d: %d ", cnt, T - (int)S.size()); } return 0; }