https://ac.nowcoder.com/acm/contest/20278/L
这题风格老cf了,首先考虑贪心,开数组记录每个字符出现的次数,将字母编号和对应出现次数纪录在结构体中,按次数多的排在前面贪心,
这里设结构体为p,id为对应字母,d为出现次数,从1到tot(tot为去重后的结构体个数)依次判定是否d还大于0,大于0则将其加到答案字符串里,并让d--,最后重复的肯定在结尾,例如cabcacc,按以上做法得到答案字符串cabcacc,末尾有多余c,但ab之间可以插个c,所以最后只需统计可插的位置及末尾多少重复即可,结合代码来看吧。
#include<bits/stdc++.h> using namespace std; const int N=100009; struct Node{ int id,d; }p[N]; int n; int tot; int M[N]; int b[N]; char s[N]; bool v[N]; int Max; bool cmp(Node a,Node b){ return a.d>b.d; } int main() { cin>>n; cin>>s; for(int i=0;i<n;i++){ if(!v[s[i]-'a']){p[++tot].id=s[i]-'a',v[s[i]-'a']=1;M[tot]=s[i]-'a';} b[s[i]-'a']++; } for(int i=1;i<=tot;i++)p[i].d=b[M[i]]; string ss=""; sort(p+1,p+1+tot,cmp); while(1){ bool f=0; for(int i=1;i<=tot;i++){ if(p[i].d>0){ p[i].d--; ss+=p[i].id+'a'; f=1; } } if(!f)break; } int cnt=0; int k=ss.size(); for(int i=0;i<k-1;i++){ if(ss[i]==ss[i+1]){ cnt++; } } if(cnt==0){ puts("yes"); cout<<ss<<endl; return 0; } char ch=ss[k-1]; int sum=0; for(int i=0;i<k-1;i++){ if(ss[i]!=ch&&ss[i+1]!=ch)sum++; } if(cnt>sum){puts("no");return 0;} else{ puts("yes"); int g=cnt; for(int i=0;i<k-g;i++){ cout<<ss[i]; if(ss[i]!=ch&&i+1<k-g&&ss[i+1]!=ch&&cnt>0){ cnt--; cout<<ch; } } } return 0; }