hihocoder-1327-分割字符串--贪心

hihocoder-1327-分割字符串--贪心

1327 : 分隔相同字符

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

给定一个只包含小写字母'a'-'z'的字符串 S ,你需要将 S 中的字符重新排序,使得任意两个相同的字符不连在一起。

如果有多个重排后字符串满足条件,输出字典序最小的一个。

如果不存在满足条件的字符串,输出INVALID。

输入

字符串S。(1 ≤ |S| ≤ 100000)

输出

输出字典序最小的答案或者INVALID。

样例输入
aaabc
样例输出
abaca

 

使用贪心的方法。本题的分析重点是: 在当前确定使用字典序最小的字符,同时要判断“如果当前使用了这个字符,后面会是合法吗?” 这个问题。

本题的关键点是: 当 cnt[ ch[i] - 'a' ] > (len + 1)/2 时候,就无法组成合法的不相邻字符串,

 

 

#include <cstdio> 
#include <cstring> 

const int MAXN = 100000 + 10; 

bool Check(const int a[], const int len, const int b){
	for(int i=0; i<len; ++i){
		if(a[i] > (b+1)/2){
			return false; 
		}
	}
	return true; 
}

int main(){
	freopen("in.txt", "r", stdin); 

	int len; 
	char ch[MAXN], ans[MAXN]; 
	int cnt[26]; 

	while(scanf("%s", ch) != EOF){
		getchar(); 
		len = strlen(ch);
		memset(cnt, 0, sizeof(cnt));  
		for(int i=0; i<len; ++i){
			++cnt[ ch[i] - 'a' ]; 
		}
		bool ans_flag = true; 

		for(int i=0; i<len; ++i){
			bool ok = false; 

			for(int j=0; j<26; ++j){ 
				if(cnt[j] > 0 && (i==0 || ans[i-1] != j + 'a' ) ){ 
					--cnt[j]; 
					bool vali = Check(cnt, 26, len-i-1); 
					ok = ok || vali;  
					if(vali){ 
						ans[i] = 'a' + j; 
						break; 
					}else{
						++cnt[j]; 
					}
				}
			} 
			if(!ok) {
				ans_flag = false; 
				break; 
			}
		}
		ans[len] = '\0'; 
		if(ans_flag){
			printf("%s\n", ans );
		}else{
			printf("INVALID\n");
		}
	}
	return 0; 
}

  

posted @ 2017-09-16 17:19  zhang--yd  阅读(301)  评论(0编辑  收藏  举报