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;
}