题意:有一个串成环的s, 他的每一位往右挪一位形成的新串为t,然后让你求串s的最小字典序。
思路:因为要求s尽可能小,那么就尽可能把小的放前面,但是要判断一下这个字符在不在这个串中,这里我直接用并查集做,如果在就不能放,然后记录每个字符前面的字母和是否标记,如果标记了就下次找的时候可以时间continue,最后就是如果超过26个字符,最后一个字符无论如何都是会入环,就特判一下就可以了
/**
* ┏┓ ┏┓+ +
* ┏┛┻━━━┛┻┓ + +
* ┃ ┃
* ┃ ━ ┃ ++ + + +
* ████━████+
* ◥██◤ ◥██◤ +
* ┃ ┻ ┃
* ┃ ┃ + +
* ┗━┓ ┏━┛
* ┃ ┃ + + + +Code is far away from
* ┃ ┃ + bug with the animal protecting
* ┃ ┗━━━┓ 神兽保佑,代码无bug
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛ + + + +
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛+ + + +
*/
#include<cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include<vector>
#include<queue>
#include<map>
#define ll long long
using namespace std;
const int N=100000+100;
int n ,m;
char s[N];
int h[200];
int w[200];
bool st[200],ss[200];
int find(int x)
{
if(h[x]!=x)h[x]=find(h[x]);
return h[x];
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n;
int sum=0;
memset(st,0,sizeof st);//标记每一位是否被使用
memset(ss,0,sizeof ss); //标记每一位是否被使用
for(int i ='a';i<='z';i++) h[i]=i;
cin>>s+1;
for(int i =1;i<=n;i++)
{
char t=find(s[i]);
if(st[s[i]]){
cout<< (char)w[s[i]];
continue;
}
for(int j='a';j<='z';j++)
{
int k=find(j);
if(k==t&&sum<25)continue;
if(ss[j])continue;
ss[j]=true;
h[s[i]]=k;
w[s[i]]=j;
st[s[i]]=true;
cout<<(char)j;
sum++;
break;
}
}
cout<<endl;
}
return 0;
}