http://codeforces.com/problemset/problem/600/C;
题意:给你一个小写字母组成的英文串,将它转换为回文串,要求,改变的字母的个数最小,移动字母不算改变字母。
所得的串字典序是最小的。最后输出所得到的串。
思路:要求改变的字母数最小那么用贪心的思想,就把原来的字母尽可能多的填入要求的串中。
首先,先把原串中的字母统计出来,开个数组存对应的字符的个数,然后从‘a’开始循环,如果对应字母的个数大于1;
如果是偶数个的话,就在所求串两端一边加一个,可以正好加完,若是奇数个的话那么按这样的操作,最后就剩下一个,那么把它加入队列。
最后操作队列中的单个的,然后补一个加到串的两端,直到串被补满。
然后再对串的一半排下序就可以了。
1 #include<stdio.h> 2 #include<algorithm> 3 #include<iostream> 4 #include<string.h> 5 int cmp(const void*p,const void*q); 6 char a[100005*2]; 7 char b[100005*2]; 8 char c[100005*2]; 9 char bb[100005*2]; 10 int aa[26]; 11 #include<queue> 12 using namespace std; 13 int main(void) 14 { 15 int n,i,j,k,p,q,l,z; 16 while(scanf("%s",a)!=EOF) 17 { 18 queue<int>que; 19 z=0; 20 memset(aa,0,sizeof(aa)); 21 l=strlen(a); 22 for(i=0; i<l; i++)//统计对应的字母有多少个 23 { 24 aa[a[i]-‘a‘]++; 25 } 26 int t=0; 27 for(i=0; i<26; i++) 28 { 29 if(aa[i]!=0) 30 { 31 if(aa[i]>=2)//大于2的先加在串的两端 32 { 33 while(aa[i]>1) 34 { 35 aa[i]-=2; 36 a[t]=i+‘a‘; 37 a[l-1-t]=i+‘a‘; 38 t++; 39 z+=2; 40 } 41 } 42 if(aa[i]==1) que.push(i);//剩下1的入队 43 44 } 45 46 47 } 48 while(!que.empty()) 49 { 50 int f=que.front(); 51 que.pop(); 52 if(z>=l) 53 { 54 break; 55 } 56 while(aa[f]>0) 57 { 58 aa[f]-=2; 59 a[t]=f+‘a‘; 60 a[l-1-t]=f+‘a‘; 61 t++; 62 z+=2; 63 if(z>l) 64 { 65 break; 66 } 67 } 68 if(z>=l)//当满了就跳出 69 { 70 break; 71 } 72 } 73 int uu; 74 if(l%2==0)//找串的一半(分奇数偶数讨论) 75 { 76 uu=l/2; 77 } 78 else uu=(l-1)/2; 79 for(i=0; i<uu; i++) 80 { 81 b[i]=a[i]; 82 } 83 qsort(b,uu,sizeof(char),cmp);//对串的一半排序 84 for(i=0; i<uu; i++) 85 { 86 printf("%c",b[i]); 87 } 88 if(l%2==1) 89 { 90 printf("%c",a[(l)/2]); 91 } 92 for(i=uu-1; i>=0; i--) 93 { 94 printf("%c",b[i]); 95 } 96 printf("\n"); 97 98 } 99 return 0; 100 } 101 int cmp(const void*p,const void*q) 102 { 103 char *w=(char*)p; 104 char *u=(char*)q; 105 return (*w-‘a‘)-(*u-‘a‘); 106 }
时间: 2024-10-14 00:05:34