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;
}
posted @ 2022-03-22 18:56  zyy2001  阅读(37)  评论(0编辑  收藏  举报