Visitors hit counter dreamweaver

poj 3274 数的哈希

     据说这题很经典噢~开始的分析也经典。题目的分析我就不多说了,具体可以参考:http://blog.csdn.net/chinaczy/article/details/5790107一看就很清楚了(感谢这位博主)。但他用的hash函数我暂时是不能理解,说以没用它的方法。自己写了个简单的hash方法,似乎还挺凑效,然后再处理冲突。一开始时,我是先hash一边,然后再来个for循环来判断每个hash值....TLE。不行啊,然后换了个方法,hash和找最大值同步进行,这样就省去了最后的一次遍历,很能节省时间。还有就是要注意前导的全零,没有的话就WA.我就错了好多次,后来看了discuss才明白的,感谢那里面的大牛。比如测试这个:

4  4     一开始我输出的是零。。才发现没有前导的零。。改了之后AC了。嘿嘿!!不错不错  通过这题,对hash又有了深刻的认识。

1

2

4

8

#include <iostream>
#include <cmath>

using namespace std;

#define MAX 100001
int a[MAX][31];
int n,k,maxlen=0,dist;

struct Hash{
     int index;
     bool used;
     Hash *next;
     Hash(){index=0; used=false; next=NULL;}
}hash[MAX];

bool cmp(int ai,int bi)
{
    for(int i=0; i<k; i++)
        if(a[ai][i]!=a[bi][i])
           return false;
    return true;
}

int main()
{
    freopen("acm.txt","r",stdin);
    int i,j,num;
    scanf("%d%d",&n,&k);
    for(i=0; i<k; i++)  //第一个放全0
    {
        a[0][i]=0;
    }
    i=1;  
    while(1)
    {
        if(i>n)
            break;
        scanf("%d",&num);
        for(j=k-1; j>=0; j--)
        {   //存储每一二进制位
            a[i][j]=num & 1;
            num=num>>1;
        }
        i++;
    }
    int tem;
    for(i=1; i<=n; i++)
    {
        for(j=k-1; j>=0; j--)
        {
               a[i][j]+=a[i-1][j];
    
        }
    }

    for(i=0; i<=n; i++)
    {
        tem=a[i][k-1];  //暂存最低位
        for(j=k-1; j>=0; j--)
           a[i][j]=abs(a[i][j]-tem);
    }

     //转存hash
     for(i=0; i<=n; i++)
     {
         int sum=0;
         bool flag=false;
         for(j=0; j<k; j++)
         {
             sum+=a[i][j]*(j+1);
         }
         if(hash[sum].used)  //冲突
         {
              Hash *tem=&hash[sum];
             if(cmp(tem->index,i))   //比较是否相等
             {
                 dist=i-hash[sum].index;
                 if(dist>maxlen)
                     maxlen=dist;
                 continue;  //继续下次
             }
             else
             {
                 while(tem->next!=NULL)
                 {
                     if(cmp(tem->next->index,i))
                     {
                         dist=i-tem->next->index;
                         if(dist>maxlen)
                              maxlen=dist;
                         flag=true;  //已经有相等的
                         break;    //跳出while
                     }
                     tem=tem->next;
                 }
             }
             
             if(!flag)//没有找到相等的
             {
                  Hash *H=new Hash();
                  H->index=i;
                  tem->next=H;
             }
         }
         else //没有冲突
         {
             hash[sum].index=i;
             hash[sum].used=true;
         }
     }
     printf("%d\n",maxlen);
    return 0;
}

 

posted @ 2012-04-11 17:46  Jason Damon  阅读(488)  评论(0)    收藏  举报