Educational Codeforces Round 2B:http://codeforces.com/contest/600/problem/C
A string is called palindrome if it reads the same from left to right and from right to left. For example "kazak", "oo", "r" and "mikhailrubinchikkihcniburliahkim" are palindroms, but strings "abb" and "ij" are not.
You are given string s consisting of lowercase Latin letters. At once you can choose any position in the string and change letter in that position to any other lowercase letter. So after each changing the length of the string doesn't change. At first you can change some letters in s. Then you can permute the order of letters as you want. Permutation doesn't count as changes.
You should obtain palindrome with the minimal number of changes. If there are several ways to do that you should get the lexicographically (alphabetically) smallest palindrome. So firstly you should minimize the number of changes and then minimize the palindrome lexicographically.
The only line contains string s (1 ≤ |s| ≤ 2·105) consisting of only lowercase Latin letters.
Print the lexicographically smallest palindrome that can be obtained with the minimal number of changes.
aabc
abba
aabcd
abcba
题目大意:给定一个字符串,可以改变一个字母,也可以改变字母的顺序(不算作改变字母),求最小改变次数下的最小回文串。
大致思路:贪心即可,从a开始取字母,每次取2个字母弄在字符串收尾,若当前前字母只剩一个,在后面找一个单数次数的字母改变,若不存在则为最中间的字母
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int len,num[257],i,j,sig,cur;
char s[200005];
int main() {
while(1==scanf("%s",s)) {
len=strlen(s);
cur=sig=0;
j='z';
memset(num,0,sizeof(num));
for(i=0;i<len;++i)
++num[s[i]];
for(i='a';i<='z';++i)
if(num[i]&1)
++sig;
for(i='a';i<='z';++i) {
while(num[i]>1) {
s[cur]=s[len-cur-1]=i;
num[i]-=2;
++cur;
}
if(num[i]) {
if(sig>1) {
while((num[j]&1)!=1)
--j;
--num[j];
--num[i];
sig-=2;
s[cur]=s[len-cur-1]=i;
++cur;
}
else if(sig==1) {
s[len>>1]=i;
sig=0;
}
}
}
printf("%s\n",s);
}
return 0;
}