数据结构之哈希(poj3274)

来源:互联网 发布:java语音识别技术 编辑:程序博客网 时间:2024/05/18 05:27

寒假集训的时候学习了一下哈希,但是一直没有练习,这几天找了几道哈希的题目,发现忘的差不多了。

做了几道题之后发现哈希真的是一个很高效的数据结构,体验到了数据结构的强大。

构建哈希表示为了能够更高效率的查找,还记得小学的时候查字典吗?其实哈希就相当于那样一个东西,他把数据按照一定的哈希函数生成一个键值,然后把所有键值相同的存在一个相同的数组中,然后查找的时候首先找它的键值,找到键值之后只用在键值相同的这个数组中查找就行了。

原理就是这样,要想真正了解哈希表,还要几道题目练习,首先哈希表可以用二维结构体存储,因为你不知道每一个键值后面有多少个元素,所以用二维结构体存储的话后面一维的大小不好确定,而且有些题目对内存的要求比较严格,每个都开那么大的话会浪费很多的内存,所以一般都会用一个数组链表。但是链表又不好写。

那么vector就能解决这个问题,因为vector是一个动态的存储结构,下面来看一道题目。

数组sum[i][j]表示从第1到第i头cow属性j的出现次数。

所以题目要求等价为:

求满足

sum[i][0]-sum[j][0]=sum[i][1]-sum[j][1]=.....=sum[i][k-1]-sum[j][k-1] (j<i)

中最大的i-j

 

将上式变换可得到

sum[i][1]-sum[i][0] = sum[j][1]-sum[j][0]

sum[i][2]-sum[i][0] = sum[j][2]-sum[j][0]

......

sum[i][k-1]-sum[i][0] = sum[j][k-1]-sum[j][0]

 

令C[i][y]=sum[i][y]-sum[i][0] (0<y<k)

初始条件C[0][0~k-1]=0

 

所以只需求满足C[i][]==C[j][] 中最大的i-j,其中0<=j<i<=n。

C[i][]==C[j][] 即二维数组C[][]第i行与第j行对应列的值相等,

那么原题就转化为求C数组中 相等且相隔最远的两行的距离i-j

这里的这个转化是很重要的,没办法转化的话就别想哈希了。题目坑点比较多。wa了好多次之后才ac。

ac代码:

#include <cstdio>#include <cstring>#include <cmath>#include <vector>using namespace std;const int N = 15000;const int Mod = 14997;struct Node{    int a[35];    int count;};vector<Node> hash[N];bool solve(Node x,Node y,int k){    for(int i=0;i<k;i++)    {        if(x.a[i]!=y.a[i])            return false;    }    return true;}int main(){    int n,k;    while(~scanf("%d%d",&n,&k))    {        int cmp[35]={0};        int max=0;        for(int i=0;i<n;i++)        {            int x;            scanf("%d",&x);            for(int j=0;j<k;j++)            {                cmp[j]+=x%2;                x/=2;            }            Node ans;            int sum=0,flag=1;            ans.a[0]=0;            for(int j=1;j<k;j++)            {                ans.a[j]=cmp[j]-cmp[0];                if(ans.a[j]!=ans.a[j-1])                    flag=0;                sum=(sum+(ans.a[j]*(j+7)))%Mod;            }            if(flag)            {                if((i+1)>max)                    max=i+1;            }            sum=(sum+15000)%Mod;            ans.count=i;            hash[sum].push_back(ans);        }        if(n==1)        {            int ok=1;            for(int i=1;i<k;i++)            {                if(cmp[i]!=cmp[i-1])                    ok=0;            }            if(ok)                printf("1\n");            else                printf("0\n");            hash[0].clear();            continue;        }        if(max>1)  //剪枝        {            printf("%d\n",max);            continue;        }        for(int i=0;i<15000;i++)        {            if(hash[i].size()>1)            {                for(int j=0;j<hash[i].size()-1;j++)                {                    for(int f=j+1;f<hash[i].size();f++)                    {                        if(solve(hash[i][j],hash[i][f],k))                        {                            int zhi=fabs(hash[i][j].count-hash[i][f].count);                            if(zhi>max)                                max=zhi;                        }                    }                }            }            hash[i].clear();        }        printf("%d\n",max);    }    return 0;}


0 0
原创粉丝点击