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

举报
小哈里 发表于 2022/05/10 22:27:48 2022/05/10
【摘要】 problem 有n片雪花,每片有6个脚,每个脚有一个长度。两片雪花是一样的当且仅当每个脚的长度顺序都一样(顺逆时针和开始位置不管)求n片雪花中是否有一样的雪花。 solution 维护一个哈希表 ...

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.\n");
            return 0;
        }
    }
    printf("No two snowflakes are alike.\n");
    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),实际可能变大,但也是常数级。

文章来源: gwj1314.blog.csdn.net,作者:小哈里,版权归原作者所有,如需转载,请联系作者。

原文链接:gwj1314.blog.csdn.net/article/details/81538349

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。