CSL 的字符串(stack)

链接:https://ac.nowcoder.com/acm/contest/551/D
来源:牛客网
 

CSL 以前不会字符串算法,经过一年的训练,他还是不会……于是他打算向你求助。
 

给定一个字符串,只含有可打印字符,通过删除若干字符得到新字符串,新字符串必须满足两个条件:

  • 原字符串中出现的字符,新字符串也必须包含。
  • 新字符串中所有的字符均不相同。
  • 新字符串的字典序是满足上面两个条件的最小的字符串。

输入描述:

 

仅一行,有一个只含有可打印字符的字符串 s。

|s|≤105|s|≤105

输出描述:

在一行输出字典序最小的新字符串。

示例1

输入

复制

bab

输出

复制

ab

示例2

输入

复制

baca

输出

复制

bac

备注:

ASCII字符集包含 94 个可打印字符(0x21 - 0x7E),不包含空格。

先放出代码:

#include<iostream>
using namespace std;
#include<bits/stdc++.h>
const int maxn=100005;
typedef long long ll;
int vis[maxn];
int used[maxn];

int main()
{
	string s;
	cin>>s;
	stack<char>v;
	
	for(int i=0;i<s.length();i++)
	{
		used[ s[i] ]++;
	}
	 
	vis[ s[0] ]=1;  
	used[ s[0] ]--;
	v.push(s[0]);
	
	for(int i=1;i<s.length();i++)
	{
		used[ s[i] ]--;
		
		if(vis[s[i]]==0)
		{
				while(!v.empty()&&v.top()>s[i]&&used[ v.top() ])
				{
					char c=v.top();
					vis[c]=0;
					v.pop();
				}
				
				v.push( s[i] );
				vis[s[i]]=1;
		}
	}
	
	string ans;
	while(!v.empty())
	{
		ans+=v.top();
		v.pop();
	}
	
	reverse(ans.begin(),ans.end());
	cout<<ans<<endl;
	
	return 0;
}


一开始不知道怎么来模拟这个字符串,需要将多个字符化为删除 成为一个,并且使最后的字典序最小,一开始并不知道怎么来模拟。最后看了大神的代码。思路是 先是将各种字符计数 ,然后用单调有序栈来存字符,字典序最小。1.如果当前栈顶的元素比要加进来的元素字典序小(假定这个栈顶字符出现数大于2,是要删除的字符),我们就不能把这个删除,那么后面的再出现这个字符,我们就得将这个删除掉;2.如果栈顶元素比要加进来的字符字典序大,我们就要将目前栈顶元素pop 掉,使字典序小一些。这样的话,我们在以后继续遇见这个字符,我们还需要 加进来(一种字符只能留一个,不能多,也不能少)。 上面的这两个情况操作我们需要一个标记数组来进行标记,看看是 第几种情况 1 还是 2,我们都需要进行标记,判断如果是第一种情况,我们后面再遇见这个字符,我们这个标记数组就可以 派上用场,就不会存进 stack 中相同的字符了。 

发布了123 篇原创文章 · 获赞 83 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/tsam123/article/details/89035913