【POJ3349】Snowflake Snow Snowflakes(哈希表判重,维护一个集合)

problem

  • 有n片雪花,每片有6个脚,每个脚有一个长度。
  • 两片雪花是一样的当且仅当每个脚的长度顺序都一样(顺逆时针和开始位置不管)
  • 求n片雪花中是否有一样的雪花。

solution

维护一个哈希表

  • 定义Hash(a1,a2,..a6) = (sum(a1..a6)+ji(a1..a6))%P
  • 对于两片雪花,当且仅当他们的hash值相同时他们相同.期望复杂度O(N(N/P)^2)

codes

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn = 100010, P = 99991;

int n, snow[maxn][6];
bool equal(int *a, int *b){
    for(int i = 0; i < 6; i++){
        for(int j = 0; j < 6; j++){
            int eq = 1;
            for(int k = 0; k < 6; k++)
                if(a[(i+k)%6] != b[(j+k)%6])eq = 0;
            if(eq)return 1;
            eq = 1;
            for(int k = 0; k < 6; k++)
                if(a[(i+k)%6] != b[(j-k+6)%6])eq = 0;
            if(eq)return 1;
        }
    }
    return 0;
}

int tot, head[maxn], Next[maxn];
int H(int *a){
    int sum = 0, mul = 1;
    for(int i = 0; i < 6; i++){
        sum = (sum+a[i])%P;
        mul = (long long)mul*a[i]%P;
    }
    return (sum+mul)%P;
}
bool insert(int *a){
    int key = H(a);
    for(int i = head[key]; i; i = Next[i])//近似O(1)
        if(equal(snow[i],a))return 0;
    tot++;
    memcpy(snow[tot],a,6*sizeof(int));
    Next[tot] = head[key];
    head[key] = tot;
    return 1;
}

int main(){
    int n;  cin>>n;
    for(int i = 1; i <= n; i++){
        int a[10];
        for(int i = 0; i < 6; i++)scanf("%d",&a[i]);
        if(!insert(a)){//如果已有,插入失败
            printf("Twin snowflakes found.
");
            return 0;
        }
    }
    printf("No two snowflakes are alike.
");
    return 0;
}

Hash表

介绍

1、哈希算法通过一个哈希函数H,将一种数据(包括字符串,数组)转化为能用变量表示,或是直接可作为数组下标的数(这样就可以O(1)判断是否存在)。
2、通过哈希函数转化的数值称为哈希值。
3、因为值域变简单,范围变小,可能造成两个原始信息被映射为相同值,称之为冲突。

具体

1、对于哈希函数,我们有以下几种常见的构造方法:
(a)除余法
选择一个适当的模数b,令H(key) = key%b。
b一般选择比较大的质数,减少冲突的几率。
(b)乘积取整法
选择一个(0,1)中的实数A, 令H(key) = M(A*key%1)。
即,key*A取小数部分乘以哈希表大小M再向下取整。
(c)基数转换法
将key看做为另一种进制的数,把他转为对应10进制数,再用除余法对他取余。
字符串哈希一般采用的方法。

2、对于冲突,我们一般采用开散列的方式解决:
对每一个哈希值开一个链表(相当于邻接表),把所有等同于同一哈希值的数字都记录下来,查找的时候遍历对应的链表。
这样期望复杂度为O(1),实际可能变大,但也是常数级。

原文地址:https://www.cnblogs.com/gwj1314/p/10200117.html