HOJ 13383 The Big Painting 二维字符串hash

The Big Painting
Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:65536KB
Total submit users: 37, Accepted users: 17
Problem 13383 : No special judgement
Problem description

Samuel W. E. R. Craft is an artist with a growing reputation. Unfortunately, the paintings he sells do not provide him enough money for his daily expenses plus the new supplies he needs. He had a brilliant idea yesterday when he ran out of blank canvas: "Why don’t I create a gigantic new painting, made of all the unsellable paintings I have, stitched together?". After a full day of work, his masterpiece was complete.
That’s when he received an unexpected phone call: a client saw a photograph of one of his paintings and is willing to buy it now! He had forgotten to tell the art gallery to remove his old works from the catalog! He would usually welcome a call like this, but how is he going to find his old work in the huge figure in front of him?
Given a black-and-white representation of his original painting and a black-and-white representation of his masterpiece, can you help S.W.E.R.C. identify in how many locations his painting might be?


给你两个字符矩阵,求一个字符矩阵在另一个矩阵里出现的次数


直接搜了一个二维字符串hash的板子,交上去了


#include<cstdio>
#include<iostream>
using namespace std;
#define maxn 2005
#define ULL unsigned long long
ULL maxSize = 4000007;
ULL seedx = 233;
ULL seedy = 23333;
struct HashString {
	ULL xp[maxn];
	ULL yp[maxn];
	ULL H[maxn][maxn];
	char s[maxn][maxn];
	int x,y;
	void init(int n, int m) {
		xp[0] = yp[0] = 1;
		x = n,y = m;
		for(int i = 1; i <= x; i++) xp[i] = xp[i - 1]*seedx;
		for(int i = 1; i <= y; i++) yp[i] = yp[i - 1]*seedy;
		return;
	}
	void initHash() {
		for(int i = 0; i < x; i++) {
			H[i][0] = s[i][0] - 'A' + 1;
			for(int j = 1; j < y; j++)
				H[i][j] = H[i][j - 1]*seedy + s[i][j] - 'A' + 1;
		}
		for(int i = 1; i < x; i++)//从1开始, 第0行是不变的
			for(int j = 0; j < y; j++)
				H[i][j] += H[i - 1][j]*seedx;
		return;
	}
	ULL askHash(int x1, int y1, int x2, int y2) { //询问以(x1, y1)为左上角, (x2, y2)为右上角的字符矩阵的hash值
		ULL ret = H[x2][y2];
		if(x1 > 0) ret -= H[x1 - 1][y2]*xp[x2 - x1 + 1];
		if(y1 > 0) ret -= H[x2][y1 - 1]*yp[y2 - y1 + 1];
		if(x1 > 0 && y1 > 0) ret += H[x1 - 1][y1 - 1]*xp[x2 - x1 + 1]*yp[y2 - y1 + 1];
		return ret;
	}
	void read()
	{
	    for(int i  =0;i<x;i++)
            scanf("%s",s[i]);
	}
}s1,s2;
int main() {
    #ifdef ACBang
        freopen("1.in","r",stdin);
    #endif // ACBang
    int x,y,n,m;
    while(scanf("%d%d%d%d",&x,&y,&n,&m)!=EOF)
    {
        s1.init(x,y);
        s1.read();
        s2.init(n,m);
        s2.read();
        s1.initHash();
        s2.initHash();
        ULL tt = s1.askHash(0,0,x-1,y-1);
        int ans = 0;
        for(int i = 0;i<n-x+1;i++)
            {
                for(int j = 0;j<m-y+1;j++)
                {
                    if(tt == s2.askHash(i,j,i+x-1,j+y-1))
                      ans ++;
                }
            }
        printf("%d\n",ans);
    }
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值