题目链接:http://codeforces.com/problemset/problem/883/H
题目大意:给一段长度为n的字符串s,想让你把s切成几段长度相同的回文串,可以改变s中字符的排列,最少可以出现切成几段。
解题思路:看了大佬写的,自己思维还是有诸多不足,也学到了vector可以用pop_back()删除最后一个元素,还学到了处理字符数量的技巧。首先,每段回文串里肯定都有一个字符是单个的,假设每段回文串都没有字符是单个的,那说明可以合成一串,假设不成立。假设有的回文串中有字符是单个的,有的没有,那长度肯定是一奇一偶不符合题目每段长度都相同的要求,假设不成立。
用vector<char>shuang,vector<char>dan分别统计出现两次和出现一次的字符。
所以可以分为以下几步:
①计算每个字符出现次数,并判奇偶,如果是偶数个就拆分成多个数量为2的字符存入(比如‘c’出现4次,那就存入两次c)shuang。如果是奇数个,就先拿一个存入dan,再把剩下的拆分成多个数量为2的字符存入shuang。
②如果没有出现数量为奇数的字符,那就最少可以只有一个回文串,直接将s输出。
③出现数量为奇数的字符,如果shuang内的字符不能平分给dan内的字符,也就是不能形成长度相同的回文串,那就把双里的字符拆成两次放入dan中,使得shuang能被dan平分。然后直接输出所有回文串即可。
代码:
1 #include<iostream> 2 #include<cstring> 3 #include<string> 4 #include<cstdio> 5 #include<vector> 6 using namespace std; 7 const int N=4e5+5; 8 9 int cnt[300]; 10 char ans[N],s[N]; 11 vector<char>dan; 12 vector<char>shuang; 13 14 int main(){ 15 int n; 16 scanf("%d",&n); 17 scanf("%s",s); 18 for(int i=0;i<n;i++){ 19 cnt[s[i]]++; 20 } 21 for(int i=0;i<=256;i++){ 22 if(cnt[i]){ 23 if(cnt[i]%2){ 24 cnt[i]--; 25 dan.push_back(i); 26 } 27 while(cnt[i]){ 28 cnt[i]-=2; 29 shuang.push_back(i); 30 } 31 } 32 } 33 if(dan.size()==0){ 34 for(int i=0;i<n/2;i++){ 35 ans[i]=ans[n-i-1]=shuang.back(); 36 shuang.pop_back(); 37 } 38 ans[n]='