poj3690 Constellations 字符串Hash

预处理出原矩阵所有PxQ的矩阵hash值,再处理出小矩阵的hash值并存在一个set中,再把其中所有已经存在的hash值删去即可。

输入顺序是N,M,T,P,Q...千万别看错了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <queue>
#include <stack>
#include <utility>
#include <map>
#define pb push_back
#define mp make_pair
#define N 1055
#define M 20005
typedef long long LL;
typedef unsigned long long ULL;

using namespace std;

int n , m , X , Y , T , ca;
char s[N][N];
ULL h[N][N] , p[N][N] , power;

int pre[999983] , mcnt;
struct node
{
  ULL x;
  int next;
}e[1000000];


void work()
{
  printf("Case %d: " , ++ ca);
  int i , j , sum;
  ULL x , y;
  for (i = 1 ; i <= n ; ++ i)
    scanf("%s" , s[i] + 1);
  for (i = 1 ; i <= n ; ++ i)
    for (j = 1 ; j <= m ; ++ j)
      s[i][j] = (s[i][j] == '*') + 1;
  power = 1 , sum = 0;
  for (i = 1 ; i <= Y ; ++ i)
    power *= 3;
  for (i = 1 ; i <= n ; ++ i)
  {
    for (j = 1 ; j <= m ; ++ j)
      h[i][j] = h[i][j - 1] * 3 + s[i][j];
    for (j = 1 ; j + Y - 1 <= m ; ++ j)
      p[i][j] = h[i][j + Y - 1] - power * h[i][j - 1];
  }
  power = 1;
  for (i = 1 ; i <= X ; ++ i)
    power *= 9973;
  memset(pre , -1 , sizeof(pre));
  mcnt = 0;
  for (j = 1 ; j + Y - 1 <= m ; ++ j)
  {
    for (i = 1 ; i <= n ; ++ i)
      h[i][j] = h[i - 1][j] * 9973 + p[i][j];
    for (i = 1 ; i + X - 1 <= n ; ++ i)
    {
      x = h[i + X - 1][j] - power * h[i - 1][j];
      y = x % 999983;
      e[mcnt] = (node){x , pre[y]} , pre[y] = mcnt ++;
    }
  }
  int ans = 0;
  while (T --)
  {
    for (i = 1 ; i <= X ; ++ i)
      scanf("%s" , s[i] + 1);
    for (i = 1 ; i <= X ; ++ i)
      for (j = 1 ; j <= Y ; ++ j)
        s[i][j] = (s[i][j] == '*') + 1;
    x = 0;
    for (i = 1 ; i <= X ; ++ i)
    {
      y = 0;
      for (j = 1 ; j <= Y ; ++ j)
        y = y * 3 + s[i][j];
      x = x * 9973 + y;
    }
    y = x % 999983;
    for (i = pre[y] ; ~i ; i = e[i].next)
      if (x == e[i].x)
      {
        ++ ans;
        break;
      }
  }
  printf("%d\n" , ans);
}

int main()
{
  while(scanf("%d%d%d%d%d" , &n,&m,&T,&X,&Y) , n)
    work();
  return 0;
}



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值