Codeforces Round #824 (Div. 2) C. Phase Shift(字符串+并查集)
https://codeforces.com/contest/1735/problem/C
题目大意:
有一个未知的字符串s,字符串s中的所有的26个小写英文字母按一定的顺序排列成一个圆圈,然后,s中的每个字母都被顺时针方向的字母替换,这样就得到字符串t。
给你一个字符串t。确定按字典顺序最小的字符串s,它可能是给定字符串t的原型。
input
5
1
a
2
ba
10
codeforces
26
abcdefghijklmnopqrstuvwxyz
26
abcdefghijklmnopqrstuvwxzy
output
b
ac
abcdebfadg
bcdefghijklmnopqrstuvwxyza
bcdefghijklmnopqrstuvwxyaz
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,LL> PII;
const LL MAXN=1e18;
const LL N=200200,M=2002;
LL father[N],vis[N],mp[N],c[N];
LL find(LL x)
{
if(father[x]!=x) father[x]=find(father[x]);
return father[x];
}
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
LL T=1;
cin>>T;
while(T--)
{
LL sum=26;
memset(mp,0,sizeof mp);
for(LL i=0;i<=27;i++)
{
father[i]=i;
vis[i]=0;
}
LL n;
cin>>n;
string s;
cin>>s;
for(LL i=0;i<n;i++)
{
LL idx=s[i]-'a'+1; //变成从1到26
if(mp[idx]!=0) c[i]=mp[idx];//如果前面已经标注过了,直接使用
else
{
bool flag=false;
for(LL j=1;j<=26;j++)//26个英文字母找一下
{
if(vis[j]==0)//必须要没有使用过的
{
LL fi=find(idx);
LL fj=find(j);
if(fi!=fj||sum==1)
{
sum--;
//cout<<fi<<" "<<fj<<endl;
father[fj]=fi;
vis[j]=1;
mp[idx]=j;
c[i]=mp[idx];
flag=true;
break;
}
}
if(flag==true) break;
}
}
}
for(LL i=0;i<n;i++)
{
//cout<<c[i]<<" ";
cout<<(char)(c[i]+96);
}
cout<<endl;
}
return 0;
}