字符串哈希-POJ3349-Snowflake Snow Snowflakes

谁说胖子不能爱 提交于 2020-03-07 18:47:58

字符串哈希-POJ3349-Snowflake Snow Snowflakes

题目:

有N片雪花,每片雪花由六个角组成,每个角都有长度。

第i片雪花六个角的长度从某个角开始顺时针依次记为ai,1,ai,2,…,ai,6。

因为雪花的形状是封闭的环形,所以从任何一个角开始顺时针或逆时针往后记录长度,得到的六元组都代表形状相同的雪花。

例如ai,1,ai,2,…,ai,6和ai,2,ai,3,…,ai,6,ai,1就是形状相同的雪花。

ai,1,ai,2,…,ai,6和ai,6,ai,5,…,ai,1也是形状相同的雪花。

我们称两片雪花形状相同,当且仅当它们各自从某一角开始顺时针或逆时针记录长度,能得到两个相同的六元组。

求这N片雪花中是否存在两片形状相同的雪花。

输入格式
第一行输入一个整数N,代表雪花的数量。

接下来N行,每行描述一片雪花。

每行包含6个整数,分别代表雪花的六个角的长度(这六个数即为从雪花的随机一个角顺时针或逆时针记录长度得到)。

同行数值之间,用空格隔开。

输出格式
如果不存在两片形状相同的雪花,则输出:

No two snowflakes are alike.

如果存在两片形状相同的雪花,则输出:

Twin snowflakes found.

数据范围

1≤n≤100000,
0≤ai,j<10000000

输入样例:
2
1 2 3 4 5 6
4 3 2 1 6 5
输出样例:
Twin snowflakes found.

题意:

n6给出n个长度位6的序列,需要判断其中是否存在两个序列“相似”。\\相似是指从一个序列中的某个位置开始,顺时针或逆时针遍历该序列,得到的结果与另一序列相同。

EG:
4 3 2 1 6 511 2 3 4 5 6样例:4 \ 3 \ 2 \ 1 \ 6 \ 5,从1开始“逆时针”遍历即可得到:1 \ 2 \ 3\ 4 \ 5 \ 6,因此这两个序列相似。

题解:

O(n2)暴力做法就是对每一个序列都枚举剩下的序列与之匹配,时间复杂度O(n^2)。

O(1)O(n)考虑优化匹配的过程,对每一个序列可以利用哈希表,以O(1)的时间查询是否存在哈希值相同的序列,\\若存在,再进一步按顺时针或逆时针确认是否相似。整个过程的时间复杂度是O(n)的。

具体落实:
6==①、用结构体带存储每个序列的6个权值,按“顺时针”、“逆时针”重载'=='。
②、输入时对每一个序列求哈希值,并判断哈希表中是否存在哈希值相同的序列,\\ \qquad若存在,进一步确认相似;若不存在,将其加入哈希表。

注意:

使autovector①、顺时针与逆时针遍历的具体代码落实要熟悉。\\②、哈希求值时,取模的值应当取的适当的小,且是质数,提高运行效率,因为也开不了太大的数组。\\③、使用auto来遍历vector。


代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#define ll long long
#define inf 0x7fffffff
using namespace std;
const int N=1e5+10;
const int mod=99991;
int n;
struct node
{
    int a[6];
    bool operator == (const node &t)const
    {
        for(int i=0;i<6;i++)
        {
            if((a[0]==t.a[i%6]   ///顺时针
               &&a[1]==t.a[(1+i)%6]
               &&a[2]==t.a[(2+i)%6]
               &&a[3]==t.a[(3+i)%6]
               &&a[4]==t.a[(4+i)%6]
               &&a[5]==t.a[(5+i)%6])||
               (a[0]==t.a[i]   ///逆时针
                &&a[1]==t.a[(i+5)%6]
                &&a[2]==t.a[(i+4)%6]
                &&a[3]==t.a[(i+3)%6]
                &&a[4]==t.a[(i+2)%6]
                &&a[5]==t.a[(i+1)%6])
               )
                return true;
        }
        return false;
    }
};

vector<node>h[mod];  ///hash表
node A[N];

int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
    {
        int sum=0;
        for(int j=0;j<6;j++) {scanf("%d",&A[i].a[j]);sum+=A[i].a[j]*2;}
        sum%=mod;

        for(auto k:h[sum])
            if(k==A[i])
            {
                cout<<"Twin snowflakes found."<<endl;
                return 0;
            }
        h[sum].push_back(A[i]);
        /*for(auto k:h[sum])
            cout<<k.a[1]<<" ";*/
    }
    cout<<"No two snowflakes are alike."<<endl;

    return 0 ;
}


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!