CF1506G Maximize the Remaining String题解

题意

给你一个字符串,你需要把这个字符串删除到每个字符只出现一次,求最后能得到的字典序最小的字符串是什么。

分析

发现最后只留一个字符,对于某一个字符,如果现在保留的序列中他的前边的位置存在一个字典序比他小的字符并且这个字典序比他小的字符在他之后还出现过,那么这个这个比他小的字符显然可以删去.所以我们可以考虑单调栈做法,我们用单调栈维护,如果现在栈首元素字典序比当前枚举的元素的字典序小,并且还出现过,那么这个元素就可以出栈.对于重复元素,我们额外开一个数组来记录当前的元素在不在单调栈中,如果在的话就忽略这个元素.最后单调栈中剩余的元素就是答案.

代码

#include<bits/stdc++.h>

using namespace std;
const int N=2e5+10;
char s[N];
int st[N*2];
int main(void){
	int T;
	scanf("%d",&T);
	while(T--){
		scanf("%s",s+1);
		vector<int>used(27),cnt(27);
		int n=strlen(s+1);
		for(int i=1;i<=n;i++)
			cnt[s[i]-'a']++;
		int top=0;
		for(int i=1;i<=n;i++){
			if(used[s[i]-'a']){
				cnt[s[i]-'a']--;
				continue;
			}
			while(top>0&&s[st[top]]<s[i]&&cnt[s[st[top]]-'a'])
				used[s[st[top--]]-'a']=0;
			cnt[s[i]-'a']--;
			used[s[i]-'a']=1;
			st[++top]=i;
		}
		for(int i=1;i<=top;i++)
			printf("%c",s[st[i]]);
		puts("");
	}	
	return 0;
}
posted @ 2021-11-10 14:09  兮水XiShui  阅读(42)  评论(0)    收藏  举报