158. 项链
题目链接
158. 项链
有一天,达达捡了一条价值连城的宝石项链,但是,一个严重的问题是,他并不知道项链的主人是谁!
在得知此事后,很多人向达达发来了很多邮件,都说项链是自己的,要求他归还(显然其中最多只有一个人说了真话)。
达达要求每个人都写了一段关于自己项链的描述: 项链上的宝石用数字 \(0\) 至 \(9\) 来标示。
一个对于项链的表示就是从项链的某个宝石开始,顺指针绕一圈,沿途记下经过的宝石,比如项链: \(0−1−2−3\),它的可能的四种表示是 \(0123、1230、2301、3012\)。
达达现在心急如焚,于是他找到了你,希望你能够编写一个程序,判断两个给定的描述是否代表同一个项链(注意,项链是不会翻转的)。
也就是说给定两个项链的表示,判断他们是否可能是一条项链。
输入格式
输入文件只有两行,每行一个由字符 \(0\) 至 \(9\) 构成的字符串,描述一个项链的表示(保证项链的长度是相等的)。
输出格式
如果两个对项链的描述不可能代表同一个项链,那么输出 \(No\),否则的话,第一行输出一个 \(Yes\),第二行输出该项链的字典序最小的表示。
数据范围
设项链的长度为 \(L\),\(1≤L≤1000000\)
输入样例:
2234342423
2423223434
输出样例:
Yes
2234342423
解题思路
最小表示法,双指针
求一个字符串的最小表示法,先复制一份到字符串结尾,初始两个指针,分别指向字符串下标的 \(0\) 和 \(1\) 出,暴力比较字符串大小,假设长度为 \(k\) 时两个字符不等,如果 \(k=n\),因为两个指针位置不相等,不难发现这个字符串存在循环节,且位置靠后的那个字符串说明已经枚举了所有情况,这时可以直接跳出循环;否则字符较大的那个指针长度到 \(k\) 都不可能是最小表示,因为存在字符较小的那个指针得到的答案更优。如果两个指针到达的位置相等,将任意一个指针向后移动一位即可
- 时间复杂度:\(O(n)\)
代码
// Problem: 项链
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/160/
// Memory Limit: 128 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// %%%Skyqwq
#include <bits/stdc++.h>
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
const int N=2e6+5;
char a[N],b[N];
int n;
int get_min(char s[])
{
int i=0,j=1;
while(i<n&&j<n)
{
int k=0;
while(k<n&&s[i+k]==s[j+k])k++;
if(k==n)break;
if(s[i+k]<s[j+k])j+=k+1;
else
i+=k+1;
if(i==j)j++;
}
int x=min(i,j);
s[x+n]='\0';
return x;
}
int main()
{
cin>>a>>b;
n=strlen(a);
memcpy(a+n,a,n);
memcpy(b+n,b,n);
int x=get_min(a),y=get_min(b);
if(strcmp(a+x,b+y))puts("No");
else
{
puts("Yes");
cout<<a+x;
}
return 0;
}