51nod1255 字典序最小的子序列

1255 字典序最小的子序列
题目来源: 天津大学OJ
基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题
收藏
关注
给出一个由a-z组成的字符串S,求他的一个子序列,满足如下条件:

1、包含字符串中所有出现过的字符各1个。
2、是所有满足条件1的串中,字典序最小的。

例如:babbdcc,出现过的字符为:abcd,而包含abcd的所有子序列中,字典序最小的为abdc。
Input
输入1行字符串S,所有字符均为小写,字符串的长度为L。(1 <= L <= 100000)。
Output
输出包含S中所有出现过的字符,每个字符各1个,并且字典序最小的S的子序列。
Input示例
babbdcc
Output示例
abdc
思路:满足字典序最小,那就得一个个加入到结果字符串中,比较尾部的字母与新加入的。如果尾部大于新加入并且尾部的字母在后面会出现,那就替换掉。
AC Code:
#include 
using namespace std;
const int AX = 1e5+66;
mapmp;
mapmp1;
char res[AX];
int main(){
	string s;
	cin >> s;
	int size = s.size();
	for( int i = 0 ; i < size ; i++ ){
		mp[s[i]] ++;
	}
	int tot = 0 ;
	for( int i = 0 ;i < size ; i++ ){
		mp[s[i]]--;
		if( mp1[s[i]] ) continue;
		if( !tot ){
			res[++tot] = s[i];
			mp1[s[i]] = 1;
		}else{
			while( true ){
				char c = res[tot];
				if( c > s[i] && mp[c] ){
					mp1[c] = 0;
					tot--;
				}else{
					res[++tot] = s[i];
					mp1[s[i]] = 1;
					break;
				}
				if( !tot ){
					res[++tot] = s[i];
					mp1[s[i]] = 1;
					break;
				}
			}
		}
	}
	for( int i = 1 ; i <= tot ; i++ ){
		cout << res[i] ;
	}cout << endl;
	return 0;
}
WA一组数据:
刚开始不明白为什么,后来仔细想想的确错了,不是一组数据的原因,是贪心的思路错了。
我开始的思路是:对于新加入的元素有两种可能:
①字符串中出现的字母中位于字母表它前面的字母都已经加入了,这时候就直接加入。
②当这个字母在字符串中出现是最后一次了还没加入,这时候必须加入了,但是加入之前要看看上一次加入的位置到这一次的部分,如果有比他小的,就按照从小到大全部加入,然后再加入当前字母。
但是当 当前字母不是最后一个出现的并且,位于前面的字母还未加入完全,那么这种情况就漏掉了。在考虑下去也过于繁琐了,因为数据不强,只wa了一组,但根本上还是思路错了。
贪心题最害怕一开始走错,后面就很容易想不出正解了,唉。继续加油。
#include 
using namespace std;
mapmp;
mapmp2; 

void update( char c ){
	int k = c-'a';
	for( int j = k + 1 ; j < 26 ; j++ ){
		mp2[(char)('a'+j)] --;
	}
	mp[c] = 0;
}

int main(){
	string s;
	cin >> s;
	int size =s.size();
	int num = 0;
	int id = -1;
	for( int i = 0 ; i < size; i ++ ){
		mp[s[i]]++;
	}
	for( int i = 0 ; i < 26 ; i++ ){
		int num = 0;
		for( int j = 0 ; j < i ; j++ ){
			if( mp[(char)(j+'a')] ){
				num ++;
			}
		}
		mp2[(char)('a'+i)] = num;
	}
	for( int i = 0 ; i < size ; i++ ){
		if( !mp[s[i]] ) continue;
		if( mp[s[i]] == 1 ){
			if( !mp2[s[i]] ){
				cout << s[i];
				update(s[i]);
				id = i;
			}else{
				while( true ){
					char tmp = s[i];
					int t = id;
					for( int j = id + 1 ; j < i ; j ++ ){
						if( mp[s[j]] && s[j] <= tmp ){
							tmp = s[j];
							id = j;
						}
					}
					if( t == id ){
						if( mp[s[i]] ){
							id = i;
							cout << s[i];
							update(s[i]);
						}
						break;
					}
					cout << s[id] ;
					update(s[id]);
				}
			}
		}else{
			if( mp[s[i]] && !mp2[s[i]] ){
				cout << s[i] ;
				update(s[i]);
				id = i;
			}
		}
		if( mp[s[i]] ){
			mp[s[i]] --;
		}
	}
	cout << endl;
	return 0 ;
}


你可能感兴趣的:(贪心)