【ybtoj高效进阶 21184】字典之序(贪心)(模拟)

98 篇文章 1 订阅

字典之序

题目链接:ybtoj高效进阶 21184

题目大意

给你一个字符串,要你找到一个字典序最小的子序列,使得每个在原串中有的字符都在这个串中出现且只出现一次。

思路

首先我们肯定是把能有的字符都找出来。

然后肯定就是贪嘛,每次从没有放的中选一个最小的可以放的放。
那问题就变成怎么判断是否可以放。

然后显然是首先要有这个字符在当前的位置后面,而且你其它没有放过的字符在后面都要出现过。
然后你直接暴力扫过去判断就可以了。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

char s[50001], kd[50001];
int n, m, l, dy[50001];
bool use[31];
bool see[31];

bool work(char c) {
	int noww = l;
	while (noww <= n && s[noww] != c) noww++;
	if (noww > n) return 0;
	memset(see, 0, sizeof(see));
	see[dy[noww]] = 1;
	for (int i = noww + 1; i <= n; i++) {
		if (!see[dy[i]]) {
			see[dy[i]] = 1;
		}
	}
	for (int i = 1; i <= m; i++)
		if (!see[i] && !use[i]) return 0;
	return 1;
}

int main() {
//	freopen("aorder.in", "r", stdin);
//	freopen("aorder.out", "w", stdout);
	
	scanf("%s", s + 1);
	n = strlen(s + 1);
	
	memcpy(kd, s, sizeof(kd));
	sort(kd + 1, kd + n + 1);
	m = unique(kd + 1, kd + n + 1) - kd - 1;
	
	for (int i = 1; i <= n; i++) dy[i] = lower_bound(kd + 1, kd + m + 1, s[i]) - kd;
	
	l = 1;
	for (int i = 1; i <= m; i++) {
		for (int j = 1; j <= m; j++)
			if (!use[j]) {
				if (work(kd[j])) {
					use[j] = 1;
					putchar(kd[j]);
					while (s[l] != kd[j]) l++;
					l++;
					break;
				}
			}
	}
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值