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

题意:

对于一个字符串,如果存在错排,输出它的一个错排。

思路:

如果当前的最多的字符次数Max>len/2,没有错排。如果有,输出时要维护当前Max>当前len/2,所以每次优先输出个数最多的那一个。下面是LZh的代码。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
int read(){
    int xx=0,ff=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')ff=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){xx=(xx<<3)+(xx<<1)+ch-'0';ch=getchar();}
    return xx*ff;
}
struct charar{
    int occ;
    int id;
}C[30];
bool mycmp1(const charar&A,const charar&B)
{return A.occ>B.occ;}
bool mycmp2(const charar&A,const charar&B)
{return A.id<B.id;}
int len;
char s[100010],ans[100010];
int have;
int main(){
    gets(s);
    len=strlen(s);
    for(int i=0;i<len;i++)
        C[s[i]-'a'].occ++;
    for(int i=0;i<26;i++)
        C[i].id=i;
    sort(C,C+26,mycmp1);
    if(C[0].occ>len/2){
        printf("impossible
");
        return 0;
    }
    have=0;
    for(int i=1;i<=25;i++){
        if(!C[i].occ)
            break;
        for(int j=0;j<len;j++)
            if(C[i].id+'a'==s[j]){
                ans[j]=C[have].id+'a';
                C[have].occ--;
                if(!C[have].occ)
                    have++;
            }
    }
    for(int j=0;j<len;j++)
        if(C[0].id+'a'==s[j]){
            ans[j]=C[have].id+'a';
            C[have].occ--;
            if(!C[have].occ)
                have++;
        }
    for(int i=0;i<len;i++)
        printf("%c",ans[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/hua-dong/p/8011187.html