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; }
我是一名在校大学生,热爱编程,虽然起步晚了些,但我会努力的。呵呵!
数据结构 算法

浙公网安备 33010602011771号