C. 字符串重排 2014新生暑假个人排位赛05
时间限制 1000 ms
内存限制 65536 KB
题目描述
给定一个字符串,求它的一个重排,使得没有两个相邻字符相同。
输入格式
第一行一个整数t,表示组数(t<10)。接下来的t行,每行一个字符串s,s中只包含小写字母,s的长度不大于1e5.
输出格式
若符合条件的重排存在,输出字典序最小的一个。
若不存在,输出-1。
输入样例
2
aabbccdd
aaaaabcd
输出样例
ababcdcd
-1
思路:这道题的数据很大,简单的模型背景使人不禁联想到贪心,只是贪心的方法很有讲究,首先,你必须保证所有的都没有存在相邻的不同的字符串才输出-1,其次,若存在得输出最小的。那就从头找一边。如果当前所有点都比后面的所有空格的一半长度+1小,只需要填最小的。如果当前所有点都与后面的所有空格的一半长度+1相等,且为奇数就一定要填那个相等的否则之后就无法填下去了。如果当前所有点都与后面的所有空格的一半长度+1相等,且为偶数就找那个最小的那个。如果当前所有点都与后面的所有空格的一半长度+1大,则肯定不可能填进去而不重复的,直接退出输出-1.
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<stdlib.h>
#include<cstring>
#include<cmath>
#include<algorithm>
//#define LOCAL
using namespace std;
int len,pre,k,num[30],compare[30];
char str[200000],ans[200000];
int main()
{
#ifdef LOCAL
freopen("input.txt","r",stdin);
#endif // LOCAL
int T;
scanf("%d",&T);
//cout<<T<<endl;
while(T--)
{
scanf("%s",str);
len=strlen(str);
memset(num,0,sizeof(num));
for(int i=0;i<len;i++)num[str[i]-'a']++;
pre=-1;
bool flag=1;
for(int i=0;i<len;i++)
{
int j;
for(j=0;j<26;j++)
{
//printf("i=%d j=%d num[%d]=%d\n",i,j,j,num[j]);
if(j==pre)continue;
if(num[j]>(len-i+1)/2)
{
flag=0;
break;
}
if(num[j]==(len-i+1)/2&&(len-i)%2==1)
{
k=j;
pre=j;
break;
}
}
if(j==26)for(k=0;k<26;k++)if(k!=pre&&num[k]!=0)break;
if(flag==0)break;
ans[i]=k+97;
num[k]--;
pre=k;
}
if(flag==0)printf("-1\n");
else {for(int i=0;i<len;i++)printf("%c",ans[i]);printf("\n");}
//printf("%s\n",ans);
}
return 0;
}