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. python的学习之路(四)

    #迭代器,取值只能用next方法,不能随意取值name = iter([11,22,33,44])print(name.__next__())print(name.__next__())print(n ...

  2. MHA搭建

    https://metacpan.org 下载perl依赖包的网站 ##################上传安装依赖包#################### mkdir /opt/soft_file ...

  3. NOIP 2017 逛公园 题解

    题面 这道题是一道不错的计数类DP: 首先我们一定要跑一遍dijkstra来求得每个点到1号点的最短路: 注意题干,题中并没有说所有点都可以到达n好点,只说了存在一条1号点到n号点的路径:所以我们在反 ...

  4. python网络编程——使用UDP、TCP协议收发信息

    UDP UDP是面向无连接的通讯协议,UDP数据包括目的端口号和源端口号信息,由于通讯不需要连接,所以可以实现广播发送. UDP传输数据时有大小限制,每个被传输的数据报必须限定在64KB之内. UDP ...

  5. 前端Ajax通过设置 timeout 参数,轮询后台API

    因为我连接的数据库在台湾,相距较远,所以conn.Open()方法打开极慢.前端Ajax访问API时,API的数据还未返回,前端Ajax访问已经超时. 所以设置一个轮询,设置相隔多少秒之后进行一次查询 ...

  6. EJS学习(四)之语法规则下

    模版函数 在 EJS 之外,提供了一些额外的模版函数来简化我们的一些工作 GIT:https://github.com/willerce/tmt-ejs-helper css()方法 快速的引用 CS ...

  7. mysql中有条件的插入语句

    今天在参加笔试的过程中,看到一道题,大概意思就是说,当满足了条件就执行插入语句,当时就蒙了,之前从来都没有考虑过满足条件才插入的情况,所以一直都是这样写的 insert into table_name ...

  8. Java APi 之 RMI远程方法调用

    一.什么是RPC RPC全称是remote procedure call,即远程过程调用.它是一种协议,用于从远程计算机上请求服务. 例如有两台服务器A和B,A上的应用想要调用B上应用的方法,但是他们 ...

  9. React 长列表修改时避免全体渲染

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <script ...

  10. Python爬虫之简单爬虫框架实现

    简单爬虫框架实现 目录 框架流程 调度器url管理器 网页下载器 网页解析器 数据处理器 具体演示效果 框架流程 调度器 #导入模块 import Url_Manager import parser_ ...