1. 程式人生 > 其它 >CF1506G Maximize the Remaining String題解

CF1506G Maximize the Remaining String題解

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;
}