【Educational Codeforces Round 2C】【贪心】最少修改数下得到字典序尽可能小回文串

来源:互联网 发布:12345数字打字软件 编辑:程序博客网 时间:2024/05/22 06:52
C. Make Palindrome
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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.

Input

The only line contains string s (1 ≤ |s| ≤ 2·105) consisting of only lowercase Latin letters.

Output

Print the lexicographically smallest palindrome that can be obtained with the minimal number of changes.

Sample test(s)
input
aabc
output
abba
input
aabcd
output
abcba


//http://blog.csdn.net/snowy_smile#include<stdio.h> #include<string.h>#include<ctype.h>#include<math.h>#include<iostream>#include<string>#include<set>#include<map>#include<vector>#include<queue>#include<bitset>#include<algorithm>#include<time.h>using namespace std;void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);}#define MS(x,y) memset(x,y,sizeof(x))#define MC(x,y) memcpy(x,y,sizeof(x))#define MP(x,y) make_pair(x,y)#define ls o<<1#define rs o<<1|1typedef long long LL;typedef unsigned long long UL;typedef unsigned int UI;template <class T> inline void gmax(T &a,T b){if(b>a)a=b;}template <class T> inline void gmin(T &a,T b){if(b<a)a=b;}const int N=2e5+10,M=0,Z=1e9+7,ms63=1061109567;char s[N];int num[128];int main(){fre();while(~scanf("%s",s)){MS(num,0);int l=strlen(s);for(int i=0;i<l;++i)++num[s[i]];int h='a';int t='z';while(h<t){while(h<t&&num[h]%2==0)++h;while(h<t&&num[t]%2==0)--t;++num[h];--num[t];}int p=0;for(int i='a';i<='z';++i){while(num[i]>=2){s[p]=s[l-1-p]=i;num[i]-=2;++p;}if(num[i]==1)s[l/2]=i;}puts(s);}return 0;}/*【题意】给你一个字符串s,s的长度在[1,2e5]之间。我们想要修改最少的字符,使得s在重组之后可以得到回文串。同时,我们还要使得,在满足上面条件的情况下,回文串的字典序尽可能小。并输出这个回文串。【类型】贪心【分析】贪心原则已经告诉你了——1,修改次数尽可能少,这意味着,如果一个字符出现次数为偶数,我们一定不修改。2,字典序尽可能小,这意味着,对于两个出现次数为奇数的字符,如果修改,我们必然修改字典序大的那个。于是做法就出来了。统计每个字符出现的次数。然后双指针,分别从'a'升序和从'z'降序,完成修改。最后,我们就按照字典序贪心输出即可。【时间复杂度&&优化】O(n)*/


0 0
原创粉丝点击