算法进阶指南 Acwing 137. 雪花雪花雪花

有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.
算法: 字符串的最小表示法
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

int snow[6],isnow[6],snows[100010][6],idx[100010];

void get_min(int *a){
    
    int ss[12];
    for (int i = 0; i <= 11; ++i)
        ss[i] = a[i % 6];
        
    int i = 0,j = 1,ans,k;
    
    while(i < 6 && j < 6){
        for (k = 0; k < 6; ++k)
            if (ss[i + k] != ss[j + k]) break;
            
        if (k == 6) break;      // 注意 这里是 k == 6 而非 k == 5,当 k == 6 的时候代表的是从不同的i,j出发,经过长度为n可以找出两条相同的子串,那么一定会由更小的循环节,且此时两指针i和j一定是位于循环节相同位置的字母上
        
        if (ss[i + k] > ss[j + k]){
            i = i + k + 1;
            if (i == j)
                i ++;
        }else if (ss[i + k] < ss[j + k]){
            j = j + k + 1;
            if (i == j)
                j++;
        }
        
        ans = min(i,j);
    }
    
    for (int i = 0; i < 6; ++i){
        a[i] = ss[i + ans];
    }
}

bool cmp2(int* a,int* b){
    for (int i = 0; i < 6; ++i){
        if (a[i] < b[i])
            return true;
        else if (a[i] > b[i])
            return false;
    }
    return false;
}

bool cmp1(int a,int b){
    for (int i = 0; i < 6; ++i){
        if (snows[a][i] < snows[b][i])
            return true;
        else if (snows[a][i] > snows[b][i])
            return false;
    }
    return false;
}


int main(){
    
    int n;
    cin>>n;
    for (int i = 0; i < n; ++i){
        for (int j = 0; j < 6; ++j){
            cin>>snow[j];
            isnow[5 - j] = snow[j];
        }
         
        get_min(snow);
        get_min(isnow);
        if (cmp2(snow,isnow)){   // 如果 snow 字典序小于 isnow
            memcpy(snows[i],snow,sizeof snow);
        }else{
            memcpy(snows[i],isnow,sizeof isnow);
        }
        idx[i] = i;
    }
    
    sort(idx,idx + n, cmp1);
    
    for (int i = 1; i < n; ++i){
        if (!cmp1(idx[i - 1],idx[i]) && !cmp1(idx[i],idx[i - 1])){  // cmp1(a,b) 判断是的是否 snows[a] <= snows[b]
            puts("Twin snowflakes found.");
            return 0;
        }
    }
    puts("No two snowflakes are alike.");

    return 0;
}
发布了423 篇原创文章 · 获赞 38 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/weixin_41514525/article/details/104705259