最小表示法(字符串)

算法思想

破环成链,将一个环,直接复制一个相同字符串,接到链后面,即 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--) {
//
//	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值