• CH1807 Necklace【Hash】【字符串】【最小表示法】


    1807 Necklace 0x18「基本数据结构」练习

    背景

    有一天,袁☆同学绵了一条价值连城宝石项链,但是,一个严重的问题是,他竟然忘记了项链的主人是谁!在得知此事后,很多人向☆同学发来了很多邮件,都说项链是自己的,要求他归还(显然其中最多只有一个人说了真话)。 ☆同学要求每个人都写了一段关于自己项链的描述: 项链上的宝石用数字0至9来标示。一个对于项链的表示就是从项链的某个宝石开始,顺指针绕一圈,沿途记下经过的宝石,比如如下项链: 1-2-3-4  它的可能的四种表示是0123、1230、2301、3012。 袁☆同学现在心急如焚,于是他找到了你,希望你能够编一个程序,判断两个给定的描述是否代表同一个项链(注意,项链是不会翻转的)。。

    描述

    给定两个项链的表示,判断他们是否可能是一条项链。

    输入格式

    输入文件只有两行,每行一个由0至9组成的字符串,描述一个项链的表示(保证项链的长度是相等的)。

    输出格式

    如果两条项链不可能同构,那么输出’No’,否则的话,第一行输出一个’Yes’,第二行输出该项链的字典序最小的表示。

    样例输入

    2234342423
    2423223434

    样例输出

    Yes
    2234342423

    数据范围与约定

    • 设L = 项链长度, 对于50%的数据L <= 100000; 对于100%的数据L <= 1000000。

    题意:

    给两个字符串,问他们是不是同构的。如果是,输出他的最小表示。

    思路:

    首先求出第一个字符串的Hash值,然后在第二个字符串后面接一倍。枚举第二个字符串起始点,求Hash值与第一个的比较,如果找到了匹配的说明是同构的。

    找到同构的之后就找第二个字符串的最小表示。每次枚举两个串的起始,找到他们不相同的开始位置,进行比较,保留较小的。

     1 #include <iostream>
     2 #include <set>
     3 #include <cmath>
     4 #include <stdio.h>
     5 #include <cstring>
     6 #include <algorithm>
     7 #include <vector>
     8 #include <map>
     9 using namespace std;
    10 typedef long long LL;
    11 #define inf 0x7f7f7f7f
    12 
    13 const int maxn = 1e6 + 5;
    14 char str1[maxn], str2[maxn * 2];
    15 unsigned long long H1, p[maxn * 2], H2[maxn * 2];
    16 
    17 int main()
    18 {
    19     scanf("%s", str1 + 1);
    20     int len = strlen(str1 + 1);
    21     p[0] = 1;
    22     for(int i = 1; i <= len; i++){
    23         p[i] = p[i - 1] * 131;
    24         H1 = H1 * 131 + str1[i] - '0';
    25     }
    26 
    27     scanf("%s", str2 + 1);
    28     for(int i = len + 1; i <= len * 2; i++){
    29         str2[i] = str2[i - len];
    30     }
    31     for(int i = 1; i <= len * 2; i++){
    32         H2[i] = H2[i - 1] * 131 + str2[i] - '0';
    33     }
    34     bool flag = false;
    35     for(int i = 1; i <= len; i++){
    36         if(H2[i + len] - H2[i] * p[len] == H1){
    37             flag = true;
    38             printf("Yes
    ");
    39         }
    40     }
    41 
    42     if(flag){
    43         int i = 1, j = 2, k;
    44         while(i <= len && j <= len){
    45             for(k = 0; k <= len && str2[i + k] == str2[j + k]; k++);
    46             if(k == len)break;
    47             if(str2[i + k] > str2[j + k]){
    48                 i = i + k + 1;
    49                 if(i == j)i++;
    50             }
    51             else{
    52                 j = j + k + 1;
    53                 if(i == j)j++;
    54             }
    55         }
    56         int ans = min(i, j);
    57         for(i = 0; i < len; i++){
    58             printf("%c", str2[ans + i]);
    59         }
    60         printf("
    ");
    61     }
    62     else{
    63         printf("No
    ");
    64     }
    65 
    66     return 0;
    67 }
  • 相关阅读:
    Android深度探索读书笔记 第四章
    Android深度探索读书笔记 第三章
    Android深度探索读书笔记 第二章
    Android深度探索第九章
    Android深度探索第十章
    Android深度探索第八章
    第六章
    第七章
    第五章
    第四章
  • 原文地址:https://www.cnblogs.com/wyboooo/p/9825196.html
Copyright © 2020-2023  润新知