标签:https aci 统计 ble 部分 依次 justify mes turn
题目链接:https://vjudge.net/problem/2882397/origin
【问题描述】
伟大的巫师给Alice和Bob周期长度的字符串2⋅n,没有重复的子字符串的长度n。循环字符串,字符si+1在si之后。同样,s1在s2n之后。
不幸的是,邪恶的琴子打乱了字符串的所有符号。帮助Alice和Bob恢复原始字符串,从而满足上述条件。
输入
第一行包含一个字符串的长度2⋅n (2≤2⋅n≤1000000)只由拉丁字母的小写组成。
输出
如果无法恢复字符串以满足条件,则在第一行打印“NO”(不带引号)。否则,在第一行打印“YES”(不带引号)。
在第二行中打印一个字符串—恢复的字符串。
如果有多个答案,请打印任何一个。
样例输入 |
样例输出 |
aa afedbc |
NO |
试题来源:Gym-102392D
试题解析
可知题目要我们判断是否可以将给定字符串进行恢复成子串无重复的字符串。所以我们可以不用管它给的字符串是否已经是满足条件的字符串。
1.如果我们要得到无重复字串的字符串我们可以这样考虑:首先我们可以将该字符串统计各个字母的个数,将其以出现次数从多到少进行排序,再依次输出相应数量的对应字母(当然这种做法必须保证出现最多次数的字母<=n)。
2.假如出现最多次数的字母出现次数>n:如果只含有这一种字母,不管如何排列,恢复的字符串必定重复;如果只含有两种字母,第一多的字母依旧>n,第二多的字母不超过两次,那么不管如何排列,恢复的字符串也必定重复(因为第一多的字母>n也就是超过一半);其他情况下,可以先将第一多的字母超过字符串一半多余的字母按照方法一进行输出,其后插入一个第二多字符,所有字母剩余部分都按照第一种方法输出即可(必定满足子串不重复条件)。
程序清单
//Gym 102392D #include<bits/stdc++.h> using namespace std; string s; int cnt[30];//cnt存储字母出现次数 int ch[30];//ch用来存储字母 bool cmp(int x,int y){ return cnt[x]>cnt[y]; } int main() { cin>>s; int len=s.size();//len为给定字符串的长度 int half=s.size()/2;//half为给定字符串一半长度 for(int i=0;i<len;i++) cnt[s[i]-‘a‘]++; for(int i=0;i<26;i++) ch[i]=i; sort(ch,ch+26,cmp); if(cnt[ch[0]]<=half){//出现次数最多的字母不超过一半长度,那可以按以下恢复字符串 cout<<"YES"<<endl; for(int i=0;i<26;i++){ for(int j=0;j<cnt[ch[i]];j++){ printf("%c",ch[i]+‘a‘); } } return 0; } else{ if(cnt[ch[1]]==0||(cnt[ch[1]]<=2&&cnt[ch[2]]==0)){//无法恢复的情况 cout<<"NO"<<endl; return 0; } else{ cout<<"YES"<<endl; for(int i=0;i<half;i++) printf("%c",ch[0]+‘a‘); cnt[ch[0]]=cnt[ch[0]]-half; cnt[ch[1]]--; printf("%c",ch[1]+‘a‘); for(int i=0;i<26;i++){ for(int j=0;j<cnt[ch[i]];j++){ printf("%c",ch[i]+‘a‘); } } return 0; } } return 0; }
标签:https aci 统计 ble 部分 依次 justify mes turn
原文地址:https://www.cnblogs.com/Mingusu/p/11968478.html