C. 易位构词
Time limit per test: 2.0 seconds
Memory limit: 256 megabytes
易位构词 (anagram),指将一个单词中的字母重新排列,原单词中的每个字母都出现有且仅有一次。例如 "unce" 可以被易位构词成 "ecnu"。在某些情况下,要求重排而成的依然是一个单词,但本题没有这种要求,因为我们根本没有词典。
我们所感兴趣的是,有些单词中的字母进行适当的重排后,可以使得构成的单词每个对应的位置上字母都不一样。例如 "unce" 和 "ecnu",就有 "u" ≠ "e", "n" ≠ "c", "c" ≠ "n", "e" ≠ "u"。现在给出一个单词,问是否存在这样一个重排。
Input
一行一个单词 s ( 1≤|s|≤105 )。单词完全由 26 个小写英文字母构成。
Output
输出一个单词。如果有多解,输出任意解。如果不存在,输出 impossible
。
Examples
input
unce
output
ecnu
input
aaaaaa
output
impossible
#include <bits/stdc++.h>
using namespace std;
string s;
int main(){
cin >> s;
int cnt[26];
memset(cnt, 0, sizeof(cnt));
for(int i = 0; i < s.size(); ++i){
cnt[s[i] - 'a']++;
}
vector<pair<int,int> > g;
for(int i = 0; i < 26; ++i){
if(cnt[i] > 0){
g.push_back(make_pair(cnt[i], i));
}
}
sort(g.begin(), g.end());
reverse(g.begin(), g.end());
string cur = "";
for(int i = 0; i < g.size(); ++i){
for(int j = 1; j <= g[i].first; ++j){
cur += 'a' + g[i].second;
}
}
string ans = "";
int pos = g[0].first;
int i = pos;
while(i < cur.size()){
ans += cur[i++];
}
i = 0;
while(i < pos){
ans += cur[i++];
}
vector<int>x[26];
for(int i = 0; i < ans.size(); ++i){
x[cur[i] - 'a'].push_back(ans[i] - 'a');
}
int poss[26];
memset(poss, 0, sizeof(poss));
string res = "";
for(int i = 0; i < s.size(); ++i){
res += 'a' + x[s[i] - 'a'][poss[s[i] - 'a']++];
}
for(int i = 0; i < s.size(); ++i){
if(s[i] == res[i]){
cout<<"impossible"<<endl;return 0;
}
}
cout<<res<<endl;
}
/*
题意:
1e5的字符串,现在需要构造一个新字符串,使得新串每一个位置上的字母和原串都不一样。
思路:
这题可以贪心处理。首先我们想到的是先把所有字母的个数计数一下,显然对问题麻烦的是出现
次数多的字母,我们把次少个字母往较多的字母的位置放,剩下的位置放最多个的字母。
*/