算法思想
破环成链,将一个环,直接复制一个相同字符串,接到链后面,即
s
t
r
i
n
g
string
string
a
a
a;
a
=
a
+
a
a=a+a
a=a+a,
接下来就是移动i,j指针,初值I=0,J=1
保证ij指针比较时都不相同
之后,k指针++,依次遍历ij指针为首的字符串,并且进行比较
以下有三种情况
如果 s[i+k]>s[j+k]那么就说明,i这边这一串更小,直接说明i指针开头长度为n的串不是最小表示,也同样说明i+1,i+2……i+k也同样不是最小表示,因为我可以取对应的j+1,j+2……j+k为首的字符串,s[i+1,i+k-1]这一串和s[j+1,j+k-1]这一串完全一样,但是比较到s[i+k]和s[j+k]的时候,就必然是s[j+k]这边胜出,所以i指针可以直接i+=k+1,(后移一个位置)
s[i+k]<s[j+k]同上
while循环比较过后,k==n,这样就说明这是一个循环串,因为ij指针不同,所以ab[],[]ab这样必然可以根据二者完全相同来构造一个循环串,因为将 ab[………]的ab放在[]后面就得到了另一串,[………]处于字符串的同一位置。
题目链接
代码实现
#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
using namespace std;
#define el '\n'
#define cl putchar('\n')
#define pb push_back
#define fir first
#define sec second
typedef long long ll;
typedef pair<int,int> pii;
typedef vector<int> vci;
typedef map<int,int> mii;
typedef mii::iterator mii_it;
typedef mii::reverse_iterator mii_rit;
const int N=2e6+10,M=1e3+10;
int T,n,m,x,y;
string a,b;
int get_min(string s){
int i=0,j=1;
while(i<n&&j<n){//保证i指针不等于j指针
int k=0;
while(k<n&&s[i+k]==s[j+k])k++;
if(k==n)break;//原字符串存在循环结
if(s[i+k]>s[j+k])i+=k+1;//j更小
else j+=k+1; //i更小
if(i==j)j++;//二者相等没必要比较
}
return min(i,j);
}
int main() {
cin.tie(0);
cout.tie(0);
cin>>a>>b;
n=a.size();
a=a+a;
b=b+b;
x=get_min(a);
y=get_min(b);
if(a.substr(x,n)==b.substr(y,n)){//判断两个最小表示法是否相同
cout<<"Yes"<<el;
cout<<a.substr(x,n);
}
else cout<<"No";
// cin>>T;
// while(T--) {
//
// }
}