[HDU2456] Constellations [2008 Asia Hefei Regional Contest Online A]

来源:互联网 发布:准确控盘源码指标公式 编辑:程序博客网 时间:2024/04/27 13:50

题意

给出一个NM的矩阵,矩阵中只有一些或者0n1000,m1000,然后另有TPQ矩阵P,Q固定且P,Q50,问这些询问中有几个是大矩阵的子矩阵。

题解

由于p,q很小,而且矩阵中只有两个字符,把每一行给hash成一个longlong的二进制数。我们把大矩阵每个位置为起点的q长度的串hash成二进制数都存起来,每次询问的时候,把小矩阵每一行给hash了然后在大矩阵中枚举位置,进行匹配。

代码

/****************************************\* Author : ztx* Title  : A - Constellations* ALG    : hash* CMT    :* Time   :\****************************************/#include <cstdio>#define Rep(i,l,r) for(i=(l);i<=(r);i++)#define rep(i,l,r) for(i=(l);i< (r);i++)#define Rev(i,r,l) for(i=(r);i>=(l);i--)#define rev(i,r,l) for(i=(r);i> (l);i--)typedef long long ll ;typedef double lf ;int CH , NEG ;template <typename TP>inline void read(TP& ret) {    ret = NEG = 0 ; while (CH=getchar() , CH<'!') ;    if (CH == '-') NEG = true , CH = getchar() ;    while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ;    if (NEG) ret = -ret ;}template <typename TP>inline void readc(TP& ret) {    while (ret=getchar(),ret!='0'&&ret!='*');/*  while (ret=getchar() , ret<'!') ;    while (CH=getchar() , CH>'!') ;*/}template <typename TP>inline void reads(TP *ret) {    ret[0]=0;while (CH=getchar() , CH<'!') ;    while (ret[++ret[0]]=CH,CH=getchar(),CH>'!') ;    ret[ret[0]+1]=0;}#include <cstring>#define  maxn  1010LL#define  maxp  60LLint kiss = 0 , n , m , t , p , q , ch , ans ;bool map[maxn][maxn] ;ll hash1[maxn][maxn] , hash2[maxp] ;int main() {int i , j , k ;//  #define READ    #ifdef  READ        freopen(".in" ,"r",stdin ) ;        freopen(".out","w",stdout) ;    #endif    while (++ kiss) {        read(n) , read(m) , read(t) , read(p) , read(q) ;        if (n+m+t+p+q == 0) break ;        ans = 0 ;        if (n < p || m < q) {            Rep (i,1,n) Rep(j,1,m) readc(ch) ;            while (t -- )                Rep (i,1,p) Rep (j,1,q) readc(ch) ;            goto ANS ;        }        Rep (i,1,n) {            Rep (j,1,m)                if (readc(ch),ch=='0') map[i][j] = false ;                else map[i][j] = true ;            hash1[i][m+1-q] = 0 ;            Rep (j,m+1-q,m)                if (map[i][j]) hash1[i][m+1-q] |= 1LL<<(m-j) ;            Rev (j,m-q,1)                if (hash1[i][j] = hash1[i][j+1]>>1LL , map[i][j]) hash1[i][j] |= 1LL<<(q-1) ;        }        while (t -- ) {            Rep (i,1,p) {                hash2[i] = 0 ;                Rep (j,1,q)                     if (readc(ch) , ch == '*')                        hash2[i] |= 1LL << (q-j) ;            }            Rev (i,n+1-p,1) Rev (j,m+1-q,1) if (hash1[i][j] == hash2[1]) {                ch = true ;                rev (k,p,1)                    if (hash1[i+k-1][j] != hash2[k]) {                        ch = false ; break ;                    }                if (ch) {                    ans += ch ;                    goto CONTINUE ;                }            }            CONTINUE:;        }        ANS:;        printf("Case %d: %d\n",kiss,ans) ;    }    #ifdef  READ        fclose(stdin) ; fclose(stdout) ;    #else        getchar() ; getchar() ;    #endif    return 0 ;}
0 0