Constellations
Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 5923   Accepted: 1164

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

题意:给定一个n*m矩阵和t个p*q的矩阵,求这t个矩阵有多少个是n*m的子矩阵。

矩阵都是01矩阵,只有'0' '*'

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <algorithm>
#include <set>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define MM(a,b) memset(a,b,sizeof(a));
const double eps = 1e-;
const int inf =0x7f7f7f7f;
const double pi=acos(-);
const int maxn=+; int ans=inf;
int n,m,t,p,q,cas=;
char text[maxn][maxn];
ull b1[],b2[];
char pat[][];
ull htmp[][],h[][]; ull base1=1e7+7;
ull base2=1e8+7; void init()
{
b1[]=;b2[]=;
for(int i=;i<;i++) b1[i]=b1[i-]*base1;
for(int i=;i<;i++) b2[i]=b2[i-]*base2; } ull calhash1()
{
ull res=;
for(int i=;i<p;i++)
{
ull k=;
for(int j=;j<q;j++)
k=k*base1+pat[i][j];
res=res*base2+k;
}
return res;
} void calhash2()
{
for(int i=;i<n;i++)
{
for(int j=;j<q;j++) htmp[i][j]=j==?text[i][j]:htmp[i][j-]*base1+text[i][j];
for(int j=q;j<m;j++) htmp[i][j]=htmp[i][j-]*base1+text[i][j]-text[i][j-q]*b1[q];
}
for(int j=;j<m;j++)
{
for(int i=;i<p;i++) h[i][j]=i==?htmp[i][j]:h[i-][j]*base2+htmp[i][j];
for(int i=p;i<n;i++) h[i][j]=h[i-][j]*base2+htmp[i][j]-htmp[i-p][j]*b2[p];//求前缀
}
} multiset<ull> st;
int main()
{
init();
int cas=;
while(~scanf("%d%d%d%d%d",&n,&m,&t,&p,&q)&&(n+m+t+p+q))
{
st.clear();
for(int i=;i<n;i++)
scanf("%s",text[i]);
for(int k=;k<t;k++)
{
for(int i=;i<p;i++)
scanf("%s",pat[i]);
st.insert(calhash1());
}
calhash2();
int ans=;
for(int i=p-;i<n;i++)
for(int j=q-;j<m;j++)
st.erase(h[i][j]); printf("Case %d: %d\n",++cas,t-st.size());
}
return ;
}

错误点:

for(int i=p;i<n;i++) h[i][j]=h[i-1][j]*base2+htmp[i][j]-htmp[i-p][j]*b2[p]

刚开始写成了htmp[i][j]=htmp[i-1][j]*base2+htmp[i][j]-htmp[i-p][j]*b2[p]

其实这样是不对的,因为这样的话htmp是代表的前缀,所以一个数会减去多次,,所以需要建立一个新的h数组

wa代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <algorithm>
#include <set>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define MM(a,b) memset(a,b,sizeof(a));
const double eps = 1e-;
const int inf =0x7f7f7f7f;
const double pi=acos(-);
const int maxn=+; int ans=inf;
int dx[]={-,,,};
int dy[]={,,,-};
int n,m,t,p,q,cas=;
char text[maxn][maxn];
ull b1[],b2[];
char pat[][];
ull has[][];
ull base1=;
ull base2=; void init()
{
b1[]=;b2[]=;
for(int i=;i<;i++) b1[i]=b1[i-]*base1;
for(int i=;i<;i++) b2[i]=b2[i-]*base2; }
ull H[][]; ull calhash1()
{
ull res=;
for(int i=;i<p;i++)
{
ull k=;
for(int j=;j<q;j++)
k=k*base1+pat[i][j];
res=res*base2+k;
}
return res;
} void calhash2()
{
for(int i=;i<n;i++)
{
for(int j=;j<q;j++) has[i][j]=j==?text[i][j]:has[i][j-]*base1+text[i][j];
for(int j=q;j<m;j++) has[i][j]=has[i][j-]*base1+text[i][j]-text[i][j-q]*b1[q];
}
for(int j=;j<m;j++)
{
for(int i=;i<p;i++) has[i][j]=i==?has[i][j]:has[i-][j]*base2+has[i][j];
for(int i=p;i<n;i++) has[i][j]=has[i-][j]*base2+has[i][j]-has[i-p][j]*b2[p];
}
} set<ull> st;
int main()
{
init();
int cas=;
while(~scanf("%d%d%d%d%d",&n,&m,&t,&p,&q)&&(n+m+t+p+q))
{
st.clear();
for(int i=;i<n;i++)
scanf("%s",text[i]);
for(int k=;k<t;k++)
{
for(int i=;i<p;i++)
scanf("%s",pat[i]);
st.insert(calhash1());
}
calhash2();
int ans=;
for(int i=;i<n;i++)
for(int j=;j<m;j++)
if(st.count(has[i][j])) st.erase(has[i][j]); printf("Case %d: %d\n",++cas,t-st.size());
}
return ;
}

TTTTTTTTTTTTTTTTTTTTT POJ 3690 0与* 二维哈希 模板 +multiset的更多相关文章

  1. C#微信公众号接口开发,灵活利用网页授权、带参数二维码、模板消息,提升用户体验之完成用户绑定个人微信及验证码获取

    一.前言 当下微信公众号几乎已经是每个公司必备的,但是大部分微信公众账号用户体验都欠佳,特别是涉及到用户绑定等,需要用户进行复杂的操作才可以和网站绑定,或者很多公司直接不绑定,而是每次都让用户填写账号 ...

  2. URAL - 1486 Equal Squares 二维哈希+二分

    During a discussion of problems at the Petrozavodsk Training Camp, Vova and Sasha argued about who o ...

  3. hdu1823(二维线段树模板题)

    hdu1823 题意 单点更新,求二维区间最值. 分析 二维线段树模板题. 二维线段树实际上就是树套树,即每个结点都要再建一颗线段树,维护对应的信息. 一般一维线段树是切割某一可变区间直到满足所要查询 ...

  4. 【URAL 1486】Equal Squares(二维哈希+二分)

    Description During a discussion of problems at the Petrozavodsk Training Camp, Vova and Sasha argued ...

  5. 【BZOJ 2462】矩阵模板 (二维哈希)

    题目 给定一个M行N列的01矩阵,以及Q个A行B列的01矩阵,你需要求出这Q个矩阵哪些在 原矩阵中出现过. 所谓01矩阵,就是矩阵中所有元素不是0就是1. 输入 输入文件的第一行为M.N.A.B,参见 ...

  6. AcWing - 156 矩阵(二维哈希)

    题目链接:矩阵 题意:给定一个$m$行$n$列的$01$矩阵$($只包含数字$0$或$1$的矩阵$)$,再执行$q$次询问,每次询问给出一个$a$行$b$列的$01$矩阵,求该矩阵是否在原矩阵中出现过 ...

  7. hdu 4819 二维线段树模板

    /* HDU 4819 Mosaic 题意:查询某个矩形内的最大最小值, 修改矩形内某点的值为该矩形(Mi+MA)/2; 二维线段树模板: 区间最值,单点更新. */ #include<bits ...

  8. poj 2155:Matrix(二维线段树,矩阵取反,好题)

    Matrix Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 17880   Accepted: 6709 Descripti ...

  9. POJ 2155 Matrix (二维线段树)

    Matrix Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 17226   Accepted: 6461 Descripti ...

随机推荐

  1. ADG环境搭建

    一:实验环境介绍PC机系统: CentOS 6.5(64位)数据库版本: Oracle 11gR2 11.2.0.4 (64位)IP地址规划:主数据库10.110.9.41 SID:orapridb_ ...

  2. ASP.NET Core中使用Autofac进行属性注入

    一些无关紧要的废话: 作为一名双修程序员(自封的),喜欢那种使用Spring的注解形式进行依赖注入或者Unity的特性形式进行依赖注入,当然,形式大同小异,但结果都是一样的,通过属性进行依赖注入. A ...

  3. pom.xml标签页名称

    pom.xml文件双击打开后,标签页显示的名称与<artifactId></artifactId>的内容相一致.

  4. CF39H 【Multiplication Table】

    这题可以枚举出每个i,j 位置的数>需要用到进制转换 int zh(int x){ long long sum=0,i=0; while(x){ sum=sum+((x%n)*pow(10,i) ...

  5. std::tr1::function和bind组件

    C++中std::tr1::function和bind 组件的使用 在C++的TR1中(Technology Report)中包含一个function模板类和bind模板函数,使用它们可以实现类似函数 ...

  6. linux 三剑客之sed常用总结

    sed 列出5-7行 [root@www ~]# nl /etc/passwd | sed -n '5,7p' -n不在处理前打印,搜索root,/p打印 nl /etc/passwd | sed ' ...

  7. redis存储数据

    redis存储结构--5种 RedisTemplate访问Redis数据结构(一)--String https://blog.csdn.net/qq_25135655/article/details/ ...

  8. 无障碍开发(三)之ARIA aria-***属性值

    aria-***属性值

  9. GitLab: Deploy keys are not allowed to push code.

    被这个问题坑了,大半天.写此博文,愿入坑的童鞋能及时托坑 一.当你第一次pull或者push gitlab远程项目的时候提示你一个该建立一个sshkey,此时你在客户端生成sshkey 二.切记要把这 ...

  10. CentOS7搭建FastDFS V5.11分布式文件系统(三)

    1.测试 前面两篇博文已对FastDFS的安装和配置,做了比较详细的讲解.FastDFS的基础模块都搭好了,现在开始测试下载. 1.1 配置客户端 同样的,需要修改客户端的配置文件: /etc/fdf ...