POJ3690:Constellations(二维哈希)

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\n", cnt, T - (int)S.size());
    }
    return 0;
}

 

posted @ 2019-03-21 20:47  heyuhhh  阅读(207)  评论(0编辑  收藏  举报