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\n");
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("\n");
61     }
62     else{
63         printf("No\n");
64     }
65 
66     return 0;
67 }

猜你喜欢

转载自www.cnblogs.com/wyboooo/p/9825196.html
今日推荐