二维hash(Uva 12886)

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=88791(题目连接)

这道道题就是让你在大矩阵里找小矩阵,用矩阵hash

用矩阵hash之前我们先定义下面这些玩意

hash1[][]记录横列的的hash值

hash2[][]记录纵向的hahs值

hash表示小矩阵的hash值

定义两个种子常数

const ULL seed1=10000007;
const ULL seed2=100000007;

两个种子的值不能相同,因为有时横向和纵向的hash值会相同。所以要用不同的种子值,orz= =

先求小矩阵的的hash值

 1 ULL get_hash()
 2 {
 3      ULL t=0;
 4     for(int i=0;i<x;i++)
 5     {
 6          ULL cnt=0;
 7          for(int j=0;j<y;j++)
 8             cnt=cnt*seed1+s[i][j];//
 9          t=t*seed2+cnt;
10     }
11     return t;
12 }

然后在大矩阵中构造小矩阵。。。。。想见代码吧= =

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#define maxn 2005
using namespace std;
typedef unsigned long long ULL;
const ULL seed1=10000007;
const ULL seed2=100000007;
char s[maxn][maxn];
char ch[maxn][maxn];
ULL hash1[maxn][maxn];
ULL hash2[maxn][maxn];
ULL hash;
ULL ans;
int x,y,n,m;
ULL get_hash()
{
     ULL t=0;
    for(int i=0;i<x;i++)
    {
         ULL cnt=0;
         for(int j=0;j<y;j++)
            cnt=cnt*seed1+s[i][j];
         t=t*seed2+cnt;
    }
    return t;
}
void count_num()
{
    ULL c=1;
    for(int i=0;i<y;i++)
    c=c*seed1; //等会求构造矩阵的hash值需要减去第j-y位置的字符的hash值,所以要进行这步。。。
    for(int i=0;i<n;i++)
    {
        ULL cnt=0;
        for(int j=0;j<y;j++)
            cnt=cnt*seed1+ch[i][j];
        hash1[i][y-1]=cnt;
        for(int j=y;j<m;j++)
        {
            hash1[i][j]=hash1[i][j-1]*seed1-ch[i][j-y]*c+ch[i][j];//求横列的hash值
        }
    }
     c=1;
     for(int i=0;i<x;i++)
        c=c*seed2;
     for(int i=y-1;i<m;i++)
     {
         ULL a=0;
         for(int j=0;j<x;j++)
             a=a*seed2+hash1[j][i];//这里因为将横列的的字符用他的hash值代替= =
         hash2[x-1][i]=a;
         if(a==hash)
            ans++;
         for(int j=x;j<n;j++)
         {
             hash2[j][i]=hash2[j-1][i]*seed2-hash1[j-x][i]*c+hash1[j][i];
                if(hash2[j][i]==hash)//相同ans++
                ans++;
         }
     }
}
int main()
{
    while(scanf("%d %d %d %d",&x,&y,&n,&m)!=EOF)
    {
        getchar();
        memset(hash1,0,sizeof(hash1));
        memset(hash2,0,sizeof(hash2));
        for(int i=0;i<x;i++)
            scanf("%s",s[i]);
        for(int i=0;i<n;i++)
            scanf("%s",ch[i]);  
        hash=get_hash();
        ans=0;
        count_num();
        printf("%llu\n",ans);
    }
    return 0;
}

 

posted @ 2015-08-10 15:22  __NaCl  阅读(406)  评论(0编辑  收藏  举报