POJ Constellations

思路(主要参考:传送门

在这里插入图片描述

代码

#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<set>
#define ull unsigned long long
using namespace std;
int N,M,T,P,Q; 
char f[1000][1000];//匹配对象
char p[1000][1000];//匹配模式 
ull Hash[1000][1000],t[1000][1000];
void compute_hash(char a[1000][1000],int n,int m)//a表示要求哈希值的矩阵,并且是n*m的
{
	const ull B1=1e9+7;
	const ull B2=1e9+9;
	
	ull t1=1;//B1的Q次方
	for(int i=0;i<Q;i++) t1*=B1;
	
	//按行方向计算哈希值
	for(int i=0;i<n;i++)
	{
		ull e=0;
		for(int j=0;j<Q;j++) e=e*B1+a[i][j];//求出起始位置为0,长度为Q的字符串的哈希值
		
		for(int j=0;j+Q<=m;j++)//枚举一下起始位置,求出第i行所有起始位置为j,长度为Q的字符串的哈希值
		{
			t[i][j]=e;
			if(j+Q<m) e=e*B1+a[i][j+Q]-a[i][j]*t1;//每次更新一下e,表示当前的哈希值,这里是列数低的是B1进制的高位	
		}	
	} 
	
	ull t2=1;//B2的P次方
	for(int i=0;i<P;i++) t2*=B2;
	
	//按列方向计算哈希值
	for(int j=0;j+Q<=m;j++)
	{
		ull e=0;
		for(int i=0;i<P;i++) e=e*B2+t[i][j];//这里就把第一次的哈希值作为了新矩阵,来再求一次哈希值
		
		for(int i=0;i+P<=n;i++)//同理去枚举一下每一个起始位置
		{
			Hash[i][j]=e;
			if(i+P<n) e=e*B2+t[i+P][j]-t[i][j]*t2;
		}	
	} 
	
}
int main()
{
	multiset<ull> s;
	int count=0;
	while(cin>>N>>M>>T>>P>>Q)
	{
		s.clear();//注意注意
		if(N==M&&N==T&&N==T&&N==P&&N==Q) break;
		for(int i=0;i<N;i++)
			cin>>f[i];
		//将所有匹配模式的哈希值放入一个multiset中,允许元素重复,方便统计、删除元素 
		for(int t=1;t<=T;t++)
		{
			for(int i=0;i<P;i++)
				cin>>p[i];
			compute_hash(p,P,Q);
			s.insert(Hash[0][0]);//因为匹配矩阵哈希值只有一个,就是从0,0开始的哈希值,所以存入multiset中
		}	
		//求匹配对象中相应的哈希值,若multiset中有则删去,说明有匹配模式在匹配对象中出现了
		compute_hash(f,N,M);//求一下对象矩阵的哈希值
		for(int i=0;i+P<=N;i++)//枚举一下起点
			for(int j=0;j+Q<=M;j++)
				s.erase(Hash[i][j]);//删除在multiset中有的哈希值,也就是匹配到的哈希值
				
		int ans=T-s.size();//删除了所有匹配到的哈希值的multiset中哈希值个数被总矩阵数量减去,就是匹配到的矩阵数量
		cout<<"Case "<<++count<<": "<<ans<<endl;
		
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值