单点时限: 2.0 sec
内存限制: 256 MB
易位构词 (anagram),指将一个单词中的字母重新排列,原单词中的每个字母都出现有且仅有一次。例如 “unce” 可以被易位构词成 “ecnu”。在某些情况下,要求重排而成的依然是一个单词,但本题没有这种要求,因为我们根本没有词典。
我们所感兴趣的是,有些单词中的字母进行适当的重排后,可以使得构成的单词每个对应的位置上字母都不一样。例如 “unce” 和 “ecnu”,就有 “u” ≠ “e”, “n” ≠ “c”, “c” ≠ “n”, “e” ≠ “u”。现在给出一个单词,问是否存在这样一个重排。
输入格式
一行一个单词 s (1≤|s|≤105)。单词完全由 26 个小写英文字母构成。
输出格式
输出一个单词。如果有多解,输出任意解。如果不存在,输出 impossible。
样例
input
unce
output
ecnu
input
aaaaaa
output
impossible
/*
思路:先考虑字符串有序的情况,比如是 aaabcc,只要将字符串右移 3 位,变成 bccaaa。那么对于无序的情况,我们可以通过排序让它有序,做完之后再按照原先字符位置排回去。
显然最多的字母出现次数大于一半的情况是不行的。否则就将每个字母的位置和字母绑定一下,按字母序对结构体进行排序。然后以字符频率最多右移后,按原来位置派回去。即:s[c[i].num]=c[(i+Max)%len].c
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct C {
char c;
int num;
};
bool cmp(C a,C b)
{
return a.c<b.c;
}
int main() {
int flag[26]= {0};
string s;
cin>>s;
int len=s.size();
C c[len];
int Max=0;
for(int i=0; i<len; i++) {
flag[s[i]-'a']++;
c[i].c=s[i];
c[i].num=i;
Max=max(Max,flag[s[i]-'a']);
if(Max>s.size()/2)
{
cout<<"impossible"<<endl;
return 0;
}
}
sort(c,c+len,cmp);
for(int i=0; i<len; i++)
s[c[i].num]=c[(i+Max)%len].c;//移位x 按原来位置排列
cout<<s;
}