hiho一下 第165周#1327 : 分隔相同字符
题目要求:
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
给定一个只包含小写字母'a'-'z'的字符串 S ,你需要将 S 中的字符重新排序,使得任意两个相同的字符不连在一起。
如果有多个重排后字符串满足条件,输出字典序最小的一个。
如果不存在满足条件的字符串,输出INVALID。
输入
字符串S。(1 ≤ |S| ≤ 100000)
输出
输出字典序最小的答案或者INVALID。
样例输入
aaabc
样例输出
abaca
《分隔相同字符》题目分析
首先我们需要分析INVALID的充分必要条件。容易看出充要条件是S中某个字符的数目超过了(|S|+1)/2。
换句话说,除非有一个字母数量 过多,否则一定可以有一个合法的重排方案。
例如样例"aaabc",5个字符中有3个'a'。这个例子'a'的数量就在临界值上,我们必须在第1、3、5个位置上都放'a'才能把所有的'a'分隔开。如果'a'的数量再多1个,比如"aaaabc",那就没办法把'a'都分隔开了,结果就是INVALID。
那么,当我们知道目前的S不是INVALID时,我们怎么求字典序最小的重排方案呢? 这里我们可以使用一个贪心策略:我们按照'a'-'z'的顺序枚举第一个字符c,如果除去c之后,S的剩余的字符仍然>不是INVALID,那么我们就把第一个字符定为c。之后我们可以用同样的策略确定第二位、第三位……,只是在确定第二位、第三位……的时候还需要要求当前字符不能与之前定下来的字符相同。
举个例子,假设S="bbbac",我们知道出现最多的'b'一共出现了3次,没超过(|S|+1)/2=3,所以至少存在一种重排方案。这时我们要确定重排之后的第一个字符。由于我们希望字典序最小,所以我们 会先尝试第一个字符是'a'行不行。假设第一个字符是'a',那么剩余的S'="bbbc",这时剩余的S是INVALID,所以我们不能把'a'放在一个字符。
然后我们再尝试把'b'放在第一个字符。这时剩余的S'是"bbac",我们知道"bbac"至少存在一个解,并且这个解不需要第一个字符一定是'b'(因为如果S'的解需要第一个字符一定是某个ch,那么S=S'+ch一定INVALID,大家可以仔细想想)。所以我们可以安全的令第一个字符是'b',一定是字典序最小的选择。
同样的贪心策略处理3个字符后之后,我们就会得到前3个字符是:"bab",这时余下的字符是"bc"。注意由于前一个字符是'b',所以此时字典序的第一选择'b'不能被选(尽管出去'b'之后剩余字符仍 然有解),所以第四个字符选'c'。
最终我们得到答案:"babcb"。
本题的关键就是每一个字符选择时,都需要判断剩余字符有没有解。由于只有'a'-'z'26个字母,判断有没有解可以认为是O(26)=O(1)即常数复杂度的。所以总复杂度是O(|S|)。
c语言代码:
#include<stdio.h>
#include<string.h>
char s[];
int az[]; char work(int x,int y,char a)
{
int i,j,k,l;
j=;
k=y/;
l=y%;
for(i=;i<;i++)
{
if(az[i]>k+l)
{
return ' ';
}else if(az[i]==k+l)
{
if(l==)
{
s[x]=i+'a';
az[i]--;
return i+'a';
}
/*else
{
j=0;
while(az[j]==0 || j+'a'==a)j++;
s[x]=j+'a';
az[j]--;
return j+'a';
}//*/
}
}
j=;
while(az[j]== || j+'a'==a)j++;
s[x]=j+'a';
az[j]--;
return j+'a';
} int main()
{
int i,j,k,l,L;
char c;
while(gets(s)!=NULL)
{
L=l=strlen(s);
memset(az,,sizeof(az));
for(i=;i<l;i++)az[s[i]-'a']++;
//for(j=0;j<26;j++)if(az[j]>0)printf("%c%d ",j+'a',az[j]);
//printf("\n");
k=;
c=' ';
for(i=;i<L;i++)
{
c=work(i,l,c);
l--;
if(c==' ')k=;
//for(j=0;j<26;j++)if(az[j]>0)printf("%c%d ",j+'a',az[j]);
//printf("\n");
}
if(k==)printf("%s\n",s);else printf("INVALID\n");
}
return ;
}
c++代码:
#include<iostream>
#include<cstring> char s[];
int letters[]; using namespace std; char deal_str(int num,int l,char c)
{
int max,i,j,k;
i=l%;
max=(l+)/;
for(k=;k<;k++){
if(letters[k]>max){
return ' ';
}else if(letters[k]==max){
if(i==){
s[num]=k+'a';
letters[k]--;
return k+'a';
}
}
}
j=;
while(letters[j]== || j+'a'==c){
j++;
}
s[num]=j+'a';
letters[j]--;
return j+'a';
} int main(){
int i,n,l,err;
char c;
while(cin>>s){
n=l=strlen(s);
memset(letters, , sizeof(letters));
for(i = ; i < n; ++i){
letters[s[i] - 'a']++;
}
err=;
c=' ';
for(i=;i<n;i++)
{
c=deal_str(i,l,c);
l--;
if(c==' '){
err = ;
}
}
if(err==){
cout<<s<<endl;
}else {
cout<<"INVALID"<<endl;;
}
}
return ;
}
c语言代码:
#include<stdio.h>
#include<string.h>
char s[100010];
int az[27];
char work(int x,int y,char a)
{
int i,j,k,l;
j=0;
k=y/2;
l=y%2;
for(i=0;i<26;i++)
{
if(az[i]>k+l)
{
return ' ';
}else if(az[i]==k+l)
{
if(l==1)
{
s[x]=i+'a';
az[i]--;
return i+'a';
}
/*else
{
j=0;
while(az[j]==0 || j+'a'==a)j++;
s[x]=j+'a';
az[j]--;
return j+'a';
}//*/
}
}
j=0;
while(az[j]==0 || j+'a'==a)j++;
s[x]=j+'a';
az[j]--;
return j+'a';
}
int main()
{
int i,j,k,l,L;
char c;
while(gets(s)!=NULL)
{
L=l=strlen(s);
memset(az,0,sizeof(az));
for(i=0;i<l;i++)az[s[i]-'a']++;
//for(j=0;j<26;j++)if(az[j]>0)printf("%c%d ",j+'a',az[j]);
//printf("\n");
k=0;
c=' ';
for(i=0;i<L;i++)
{
c=work(i,l,c);
l--;
if(c==' ')k=1;
//for(j=0;j<26;j++)if(az[j]>0)printf("%c%d ",j+'a',az[j]);
//printf("\n");
}
if(k==0)printf("%s\n",s);else printf("INVALID\n");
}
return 0;
}
c++代码:
#include<iostream>
#include<cstring>
char s[100010];
int letters[27];
using namespace std;
char deal_str(int num,int l,char c)
{
int max,i,j,k;
i=l%2;
max=(l+1)/2;
for(k=0;k<26;k++){
if(letters[k]>max){
return ' ';
}else if(letters[k]==max){
if(i==1){
s[num]=k+'a';
letters[k]--;
return k+'a';
}
}
}
j=0;
while(letters[j]==0 || j+'a'==c){
j++;
}
s[num]=j+'a';
letters[j]--;
return j+'a';
}
int main(){
int i,n,l,err;
char c;
while(cin>>s){
n=l=strlen(s);
memset(letters, 0, sizeof(letters));
for(i = 0; i < n; ++i){
letters[s[i] - 'a']++;
}
err=0;
c=' ';
for(i=0;i<n;i++)
{
c=deal_str(i,l,c);
l--;
if(c==' '){
err = 1;
}
}
if(err==0){
cout<<s<<endl;
}else {
cout<<"INVALID"<<endl;;
}
}
return 0;
}
hiho一下 第165周#1327 : 分隔相同字符的更多相关文章
- 圆内,求离圆心最远的整数点 hiho一下第111周 Farthest Point
// 圆内,求离圆心最远的整数点 hiho一下第111周 Farthest Point // 思路:直接暴力绝对T // 先确定x范围,每个x范围内,离圆心最远的点一定是y轴两端的点.枚举x的范围,再 ...
- hiho一下 第115周:网络流一•Ford-Fulkerson算法 (Edmond-Karp,Dinic,SAP)
来看一道最大流模板水题,借这道题来学习一下最大流的几个算法. 分别用Edmond-Karp,Dinic ,SAP来实现最大流算法. 从运行结过来看明显SAP+当前弧优化+gap优化速度最快. hi ...
- .NET如何将字符串分隔为字符
.NET如何将字符串分隔为字符 如果这是一道面试题,答案也许非常简单:.ToCharArray(),这基本正确-- 我们以"AB吉
- 【hiho一下第77周】递归-减而治之 (MS面试题:Koch Snowflake)
本题是一道微软面试题,看起来复杂,解出来会发现其实是一个很简单的递归问题,但是这道题的递归思路是很值得我们反复推敲的. 原题为hihocoder第77周的题目. 描述 Koch Snowflake i ...
- hiho一下 第207周
题目1 : The Lastest Time 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 What is latest time you can make with ...
- hiho一下第128周 后缀自动机二·重复旋律5
#1445 : 后缀自动机二·重复旋律5 时间限制:10000ms 单点时限:2000ms 内存限制:512MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为一段数构成的数 ...
- 【hiho一下】第一周 最长回文子串
题目1:最长回文子串 题目原文:http://hihocoder.com/contest/hiho1/problem/1 [题目解读] 题目与 POJ 3974 palindrome 基本同样.求解最 ...
- Solution: 最近公共祖先·一 [hiho一下 第十三周]
题目1 : 最近公共祖先·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho最近发现了一个神奇的网站!虽然还不够像58同城那样神奇,但这个网站仍然让小Ho乐在其中 ...
- hiho一下十六周 RMQ-ST算法
RMQ-ST算法 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho在美国旅行了相当长的一段时间之后,终于准备要回国啦!而在回国之前,他们准备去超市采购一些当 ...
随机推荐
- [从Paxos到ZooKeeper][分布式一致性原理与实践]<二>一致性协议[Paxos算法]
Overview 在<一>有介绍到,一个分布式系统的架构设计,往往会在系统的可用性和数据一致性之间进行反复的权衡,于是产生了一系列的一致性协议. 为解决分布式一致性问题,在长期的探索过程中 ...
- javascript性能优化之Dom编程性能调优总结
1.最小化的Dom访问,在一次Dom访问做尽可能多的操作: 2.使用局部变量存放指向反复访问的元素节点的Dom引用,原则上js代码中不应该重复获取同一个元素节点,除非它在运行过程中发生改变: 3.对元 ...
- idea 新建一个java项目并运行
这个只能算是个笔记,参考:参考文档 打开Idea,选择create new project,如图 或选择File ——> New——>Project... 出现以下界面,选中Java,然后 ...
- Linux Kernel Stack
整理一些杂乱的内容.以下x86架构. Linux 内核栈大小 内核栈大小是固定的,默认为8k,曾经有选项可以设置为4k栈.由于大小固定,申请过大的栈内存,或者函数调用层次过深,都可能导致栈溢出. 关注 ...
- Android 1.5-7.0(持续更新)安全机制一览
Android 1.5 ProPolice to prevent stack buffer overruns (-fstack-protector),在缓冲区buffer与返回地址之间加入Canary ...
- 服务器上安装caffe的过程记录
1. 前言 因为新的实验室东西都是新的,所以在服务器上要自己重新配置CAFFE 这里假设所有依赖包学长们都安装好了,我是没有sudo权限的 服务器的配置: CUDA 8.0 Ubuntu 16.04 ...
- numpy中的复合数组
1.复合数组的创建 # 复合数组,最重要的是定义dtype a = np.array([('ABC', [1, 2, 3])], dtype="U3, 3i4") print(a) ...
- Unity 3D与Android Studio安卓交互之-导出jar包
u3d与安卓 jar 包交互 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分享 ...
- 服务器死机 导致 mongo 挂掉
1.删除mongod.lock和mongodb.log日志文件 2.携带参数重新启动 mongod --dbpath=/var/lib/mongo --port=27017 --fork --logp ...
- java-方法重写的注意事项
1.父类中私有方法不能被重写.因为父类的私有方法子类根本就无法继承. 2.子类重写父类方法时,访问权限不能更低.最好就一致. 3.父类静态方法,子类也必须通过静态方法进行重写.其实这个算不上方法重写, ...