CodeForces 797C Minimal string

Petya recieved a gift of a string s with length up to 105 characters for his birthday. He took two more empty strings t and u and decided to play a game. This game has two possible moves:

  • Extract the first character of s and append t with this character.
  • Extract the last character of t and append u with this character.

Petya wants to get strings s and t empty and string u lexicographically minimal.

You should write a program that will help Petya win the game.


题意为给你一个序列,操作1为把字符串s的第一个字母放在字符串t的尾部,操作2为把t的尾部字母放在u的尾部。现在要求这样操作完下来,字典序最小的u。

首先我们会很容易的发现t就是一个栈,根据先进后出的原则,我们可以想到一种贪心策略:当栈顶元素后面没有比它小的了,就把它pop出来,放在u里。现在问题就转化成了,如果求第i位以后最小的字符,这个就是一个小递推了。我们用dp[i]表示到达第

i位后面最小的元素。由于是算的后面,所以需要使用倒推,也很容易想到方程为dp[i]=min(dp[i+1],s[i]);即当前位及以后的最小,是他下一位最小,或者就是它自己。

这样求出来之后就可以进行模拟,每次发现栈顶是现在后面最小的时就pop出来,最后如果还有残余,就只能按顺序pop了。

下附AC代码。

#include<iostream>
#include<stack>
#include<string.h>
#define maxn 100005
using namespace std;
string s;
stack<char> st;
char dp[maxn];
int main()
{
	cin>>s;
	char p='z'+1;
	dp[s.size()]=p;
	for(int i=s.size()-1;i>=0;i--)
	{
		dp[i]=min(dp[i+1],s[i]);
	}
	
	for(int i=0;i<s.size();i++)
	{
		char temp=s[i];
		if(dp[i]<s[i])
		{
			st.push(s[i]);
		}
		else
		{
			cout<<s[i];
			while(!st.empty())
			{
				char now=st.top();
				if(dp[i+1]>=now)
				{
					st.pop();
					cout<<now;
				}
				else 
				break;
			}
		}
	}
	while(!st.empty())
	{
		char now=st.top();
		st.pop();
		cout<<now;
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值