1. 程式人生 > >CH1807 Necklace【Hash】【字串】【最小表示法】

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 }