5.21周赛题解
神奇的魔法
题意:
有A,B两个字符串,B可以重新排列,问当B重新排列后,能包含A所有子串且字典序最小的B串是什么,如果不能输出impossible。
题解:
因为要包含A的所有子串,自然要包含A本身。所以这题可以看成求B重新排列后能包含A且字典序最小。
首先B中一定要包含A的所有字符,所以一开始判断如果B中的字符不能包含A中的所有字符(即数量不够)的话,直接输出impossible。
在确定可以包含的情况下, 只需求字典序最小的情况就行。因为要包含A不变,且还要B字典序最小,所以可以让B中去掉A后小于等于A[0]的字符都按顺序插在A的前面,大于A[0]的字符都按顺序插在A的后面,但是这样有个问题。
举个例子:A为bc,B为cbbb,按照刚刚的做法的话,先选出A,再将剩下的按顺序插到A前面,即bbbc,在这里没有问题,但是另一种情况,A为ba,B为abbb,再按刚刚的做法,就会出现bbba,显然这不是字典序最小的情况,观察发现是A本身的第二位是要比第一位小的,所以在 A串前插入的时候不能直接将小于等于A[0]的字符插入,而是小于A[0]才行。所以要判断A串本身的情况,如果A[1]<A[0],那么插入的时候前面是小于,反之是小于等于,如果A[0]=A[1],则继续判断A[1]和A[2]。
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
#define int128 __int128
#define endl '\n'
#define lowbit(x) ((x)&(-x))
#define ls(x) x<<1
#define rs(x) (x<<1)|1
const double PI = acos(-1.0);
typedef pair<int,int> pii;
const ll inf = 1e18;
const double eps = 1e-5;
const int modn = 998244353;
const int N = 1e5+5;
int c[30];
void solve(){
for(int i=0;i<30;i++) c[i]=0;
string a,b;
cin>>a>>b;
for(int i=0;i<b.length();i++) c[b[i]-'a']++;
string now=a;
bool fl = 1;
for(int i=0;i<a.length();i++){
char x = a[i];
if(c[x-'a']==0){
fl = 0;
break;
}else{
c[x-'a']--;
}
}
if(!fl){
cout<<"impossible"<<endl;
return;
}
fl = 1;
for(int i=1;i<a.length();i++){
if(a[i]-a[i-1]<0){
fl = 0;
break;
}else if(a[i]-a[i-1]>0){
break;
}
}
if(fl){
int idx = a[0]-'a';
for(int i=0;i<=idx;i++){
for(int j=0;j<c[i];j++){
cout<<(char)(i+'a');
}
}
cout<<now;
for(int i=idx+1;i<26;i++){
for(int j=0;j<c[i];j++){
cout<<(char)(i+'a');
}
}
}else{
int idx = a[0]-'a';
for(int i=0;i<idx;i++){
for(int j=0;j<c[i];j++){
cout<<(char)(i+'a');
}
}
cout<<now;
for(int i=idx;i<26;i++){
for(int j=0;j<c[i];j++){
cout<<(char)(i+'a');
}
}
}
cout<<endl;
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int _=1;
cin>>_;
//getchar();
while(_--){
solve();
}
return 0;
}

浙公网安备 33010602011771号