题目非常简单,就是用有限的字符构造一个回文字串最多的字符串。
啥?你问我回文是什么?出门右转百度一下。
回文,意味着一个序列共有 n 项,∀i,ai=an−i+1。
但是,和子序列不同,字串必须是连续的!
那我们用样例举个例?
oolol
众所周知,它共有 8 个回文字串,分别是:
o,o,l,o,l,oo,olo,lol;
但如果我们把它变成 ololo 的话,就会有 9 个:
o,l,o,l,o,olo,lol,olo,ololo;
那我们考虑特殊情况:
1:ABABABA......;
这种情况一定有奇数个字符且只有两种;第 2 种字符的数量为第 1 种的数量减 1。
这种情况下,回文子串的数量 =(2n+1)2。
然而,这种情况受限:第一不得有多于两种字符;第二必须有奇数个字符。
那我们能否考虑到第二种特殊情况??
2:AAAA......ABBBB......BC......C
这种情况的回文子串数量为:
设 =aint(A) 为字符 A 的数量,那么总数就是:
2a33×(a33−1)+2a34×(a34−1)+2a35×(a35−1)+......+2a127×(a127−1)
因为 ASCII:32 为空格,且以下的都是 \ X 之类的,所以我们从 ASCII:33 开始。
这个公式怎么推出来的呢?
首先,对于一个有 5 个字符 A 的序列,它的回文子串有:
A,A,A,A,A,AA,AA,AA,AA,AAA,AAA,AAA,AAAA,AAAA,AAAAA
因为子串必须连续,所以只有 15 个;
而我们的子串数量,总长度为 n 的长度为 m 的子串共有 n−m 个;
而按照数列求和公式,结果应该是:2n×(n−1);
所以,能够求出如上的公式。
那么……我们去求解,但还差一步:
样例输出:ololo(9)
按此方法:oooll(9)
样例输出:abccbaghghghgdfd(29)
按此方法:aabbccddfgggghhh(29)
我们这时已经证明了此方法是正确的,那么我们就——上代码!
#include<bits/stdc++.h>
using namespace std;
char s[100001];
int main(){
int n;
cin>>n>>s;
sort(s,s+n,cmp);
cout<<s;
return 0;
}
(没错就这么简单)
其实很多人都没想到,sort 是可以对字符排序的!
无论你是从大到小,还是从小到大,都不影响,只要相同的两个字符在一起,就一定会得到最大值。
类似于桶排序的去重,最后输出几个数,从大到小枚举还是从小到大枚举不重要。
输入,排序,输出,结束。
时间复杂度 O(n×log2n)。
可通过本题。
感谢各位在评论区 hack 的大佬们~