hdu 6046 hash
题:
OwO http://acm.hdu.edu.cn/showproblem.php?pid=6046
(2017 Multi-University Training Contest - Team 2 - 1002)
解:
设A矩阵为1e3*1e3的那个矩阵,另一个叫B矩阵
首先对A矩阵进行预处理,每一行中的每一个点的哈希值为这个点和其右边63个点的组合值(总计64个点)(如果右边没63个点了那就不做了),放入hashmap中
然后对B矩阵进行扫描。
想象把很多个A矩阵铺在B矩阵上面,使A矩阵有预处理的部分铺满B矩阵
那么对B矩阵每1000行枚举一行,每900列枚举一列,则这些行列的交叉点钟必然有一个点存在于A矩阵中。
由这个点的哈希值(就是前文说的该点对应的64个点的组合值)那么找出这个点,并且由hashmap得知这个点在A矩阵中的位置,就可以得知A矩阵在B矩阵中的具体位置。
(思路来源为某其他博客)
#include <iostream> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> using namespace std; typedef unsigned long long ll; const ll hashM=1200044; const ll hashmod=1442441; ll hashval[hashM],hashtol; int hashnxt[hashM],hashpos[hashM],hashid[hashmod]; void hashInit() { hashtol=0; memset(hashid,0,sizeof(hashid)); } void hashInsert(ll val,int pos) { int tmp=val%hashmod; hashtol++; hashval[hashtol]=val; hashpos[hashtol]=pos; hashnxt[hashtol]=hashid[tmp]; hashid[tmp]=hashtol; } int hashFindpos(ll val) { int tmp=val%hashmod; for(int i=hashid[tmp];i;i=hashnxt[i]) if(hashval[i]==val) return hashpos[i]; return -1; } const int N=1000; const int M=1044; const int bas=1024; const int cps=64; char s[M][M]; inline unsigned sfr(unsigned h, unsigned x) { return h >> x; } int f(ll i, ll j) { ll w = i * 1000000ll + j; int h = 0; for(int k = 0; k < 5; ++k) { h += (int) ((w >> (8 * k)) & 255); h += (h << 10); h ^= sfr(h, 6); } h += h << 3; h ^= sfr(h, 11); h += h << 15; return sfr(h, 27) & 1; } ll hashtmp[M]; bool check(int x0,int y0) { int i,j; for(i=1;i<=N;i++) for(j=1;j<=N;j++) if(f(x0+i-1,y0+j-1)!=(s[i][j]-'0')) return false; return true; } void solve(int cas) { int i,j,k,x,y,tmp,x0,y0; ll tmpval; for(i=0;i<1000;i++) //1000 for(j=0;j<=1111;j++) //900 { tmpval=0; for(k=1;k<=cps;k++) tmpval=(tmpval<<1)+f(i*1000+1,j*900+1+k-1); tmp=hashFindpos(tmpval); if(tmp!=-1) { y=tmp%bas; x=(tmp-y)/bas; x0=i*1000+1; y0=j*900+1; x0-=(x-1); y0-=(y-1); if(check(x0,y0)) { printf("Case #%d :%d %d\n",cas,x0,y0); return ; } } } } int main() { int T,tmp,i,j,k; ll tmpval; cin>>T; for(int cas=1;cas<=T;cas++) { hashInit(); for(i=1;i<=N;i++) scanf("%s",s[i]+1); for(i=1;i<=N;i++) { hashtmp[0]=0; for(j=1;j<=N;j++) hashtmp[j]=(hashtmp[j-1]<<1)+(s[i][j]-'0'); for(j=1;j+cps-1<=N;j++) hashInsert(hashtmp[j+cps-1],i*bas+j); } solve(cas); } return 0; }