易位构词 (anagram),指将一个单词中的字母重新排列,原单词中的每个字母都出现有且仅有一次。例如 “unce” 可以被易位构词成 “ecnu”。在某些情况下,要求重排而成的依然是一个单词,但本题没有这种要求,因为我们根本没有词典。
我们所感兴趣的是,有些单词中的字母进行适当的重排后,可以使得构成的单词每个对应的位置上字母都不一样。例如 “unce” 和 “ecnu”,就有 “u” ≠ “e”, “n” ≠ “c”, “c” ≠ “n”, “e” ≠ “u”。现在给出一个单词,问是否存在这样一个重排。
Input
一行一个单词 s ( 1≤|s|≤105 )。单词完全由 26 个小写英文字母构成。
Output
输出一个单词。如果有多解,输出任意解。如果不存在,输出 impossible
。
Examples
unce
ecnu
aaaaaa
impossible
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;
#define INF 100001
typedef struct word
{
char w;
int pos;
}Word;
bool cmp1(Word &a,Word &b)
{
if(a.w==b.w)
return a.pos<b.pos;
return a.w<b.w;
}
bool cmp2(Word &a,Word &b)
{
return a.pos<b.pos;
}
Word w[INF];
int sum[26];
char str[INF];
int main()
{
int len,i,j;
memset(sum,0,sizeof(sum));
gets(str);
len=strlen(str);
for(i=0;i<len;i++)
{
w[i].w=str[i];
w[i].pos=i;
sum[str[i]-'a']++;
}
int max=sum[0];
for(i=1;i<26;i++)
{
if(max<sum[i])
max=sum[i];
}
if(max>len/2)
printf("impossible\n");
else
{
sort(w,w+len,cmp1);
char tmp[INF];
for(i=0;i<len;i++)
tmp[i]=w[i].w;
for(i=0;i<len;i++)
{
w[i].w=i-max>=0?tmp[i-max]:tmp[i+len-max];//向右移动max位
}
sort(w,w+len,cmp2);
for(i=0;i<len;i++)
printf("%c",w[i].w);
printf("\n");
}
return 0;
}
本题思路如果想到按字母排序就比较简单。对给定的字符串用结构体来表示。只要按照字母排序后的字符串中出现次数最多的字母不超过总数的一半,就能够找到易位构词,否则,输出impossible。在能找到的情况下,对排序后的字符串向右移动max位(注意此时采用的是赋值,在位置不变的情况下移动字母),最后在按照序号排序就可以了。举个例子:
输入:uexey(从左到右位置序号:0,1,2,3,4)
按字母排序后:eeuxy(从左到右位置序号:1,3,0,2,4)
向右移动max位(此处为2):xyeeu(从左到右位置序号:1,3,0,2,4)
按位置排序(此时已为易位构词,和输入对应即可):exeyu