怎么hash网上已经说得很清楚,我就不多说了。
我看的这个博客: http://hi.baidu.com/aconly/blog/item/9d1ed1122a29af876538db0b.html
直接贴一下我的代码, 也有一些我做的过程中遇到的问题:
#include <iostream> #include <cstring> #include <cstdio> using namespace std; #define K 33 #define N 100005 #define SIZE 200003 //tableSize 取满足4 * k + 3的质数,且闭散列使装载因子<=0.5,所以tableSize取总元素个数的2倍 int sum[N][K], a[N][K]; int hash[SIZE]; inline int hashcode(int v[], int k) //网上的hash函数,据说是折叠法 { int val = 0; for (int i = 1; i < k; i++) val = ((val << 2) + (v[i] >> 4)) ^ (v[i] << 10); val = val % SIZE; val = val < 0 ? val + SIZE : val; return val; } int main() { int n, k, id; int i, j, r, ans = 0; scanf("%d %d", &n, &k); memset(sum[0], 0, sizeof(sum[0])); memset(hash, -1, sizeof(hash)); memset(a[0], 0, sizeof(a[0]));//注意: hash[hashcode(a[0], k)] = 0; // 下标从1开始,但是下标为0也必须加入散列表中,因为如果 // 1,2, 3,4是平衡的了,我们比较的是,a[4]和a[0](而不是a[1])是否对应相等。 for (i = 1; i <= n; i++) //下标从1开始 { scanf ("%d", &id); for (j = 0; j < k; j++) { sum[i][j] = sum[i - 1][j] + (1 & (id >> j)); a[i][j] = sum[i][j] - sum[i][0]; } int p = hashcode(a[i], k), m = 0; while (hash[p] != -1) { for (r = 1; r < k; r++) if (a[hash[p]][r] != a[i][r]) break; if (r == k) { if (ans < i - hash[p]) ans = i - hash[p]; break; //hash[p]的值是所有映射到p这个地址的a[i]数组中最小的i值,所以一旦找到就可直接跳出循环 } p += 2 * (++m) - 1; //平方探测法 if (p >= SIZE) p -= SIZE; } if (hash[p] == -1) //如果没有搜索到,则将目前的插入到表中 hash[p] = i; } printf("%d\n", ans); return 0; }