首先看题目:
一个非空字符串叫做回文串。如果它从左到右,从右到左读相同,那么它就是回文串。 例如,“ABCBA”,“A”和“ABBA”都是回文串,而“ABAB”和“XY”则不是。
如果可以通过从字符串的开头和结尾删除一些(可能为零)字符来从该字符串获得新字符串, 则新字符串叫做另一个字符串的子字符串。 例如,“ABC”、“AB”和“C”是字符串“ABC”的子串,而“AC”和“D”不是。
我们把字符串的“回文计数”定义为回文的子串个数。 例如,字符串“aaa”的回文计数是6,因为它的所有子字符串都是回文, 而字符串“abc”的回文计数是3,因为只有长度为1的子字符串是回文。
给你一个字符串S。你可以任意地重新排列它的字符,求它的回文计数最大值。
输入格式:
第一行包含整数n(1≤n≤100000)表示字符串s的长度。
第二行包含字符串S,它由n个小写字母组成。
输出格式:
输出字符串t,(它是字符串s的一种排列) 此外,t应该具有最大回文计数的可能值。
如果有多个这样的字符串,输出它们中的任何一个。
首先考虑只有两种元素的字符串,假设有多个a和一个b那么无论怎么放置这个b,只有b在这串a的最前面或者最后面时,这串字符串的回文计数最大。
接下来考虑有两个b的情况,发现只有两个b放在一起时,回文计数最大。
那么考虑三种元素的情况,发现如果三种元素个数相同,那么只需要把同一元素放在一起即可。如果个数不同,则按照个数多少排序即可。例如abbccc或者cccbba。这两个字符串回文计数都是最大的。
那么推广到多个,只需要按照字符出现次数排序然后依次输出即可。
#include <iostream>
#include <algorithm>
using namespace std;
//#define DEBUG
int main()
{
static char a[100001];
int n,b[26]={0};//统计字符出现次数
int *ps[26];//保存指向b中每个元素的指针
cin >> n >> a;
for(int i=0;i<26;i++){
b[i]=count(a,a+n,i+'a');//统计并存入b
ps[i]=b+i;//保存指针
}
sort(ps,ps+25,[](int *p1,int *p2){return *p1>*p2;});
//排序,这里对指针排序而没有改变原来数组的元素位置
#ifdef DEBUG
for(int i=0;i<26;i++){
cout << *ps[i] << endl;
}
#endif
for(int i=0;i<26;i++){
for(int j=0;j<*ps[i];j++){
cout << char(ps[i]-b+'a');
}
}
return 0;
}
这里调用了algorithm库下的sort函数,因为排序时不想打乱原来数组的顺序,所以用了对指针进行了排序。