4.1 B 最小字典序字符串
题目概括一下是给一个串s, 提供两个空串t,u。通过一下两个操作:
- s的第一个字符移动到t末尾
- t的最后一个字符移动到u末尾 求出能得到的最小字典序。
贪心+栈的题目, 对于结果u串, 当前位置上的字符要么从s串中来, 要么从t串中来。 若u任意位置上的选择都是最小的, 那么总的字典序也是最小的 证明:
u1: ... ... ... a ... ...
u2: ... ... ... b ... ...
若 a 的字典序小于 b 的字典序, 那么根据字典序的定义, u1的字典序就小于u2的字典序。u1才是正确结果。
当前位置可以从s串和t串中来:
- 若s串存在能选的最小元素小于t串末尾, 则将其以及之前的字符都加入到t串, 并把该元素从t串末尾移到u串末尾
- 若大于等于, 则把t串末尾放到u串末尾
#include <iostream>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
using namespace std;
const int N = 1e5 + 10;
char s[N], u[N], t[N];
int top_u = -1, topt = -1;
char min_c[N];
int n;
int main()
{
cin >> s;
n = strlen(s);
min_c[n] = 'z';
for (int i = n - 1; i >= 0; i--)
min_c[i] = min(s[i], min_c[i + 1]);
for (int i = 0, j = 0; i < n; i = j)
{
if (topt == -1 || t[topt] > min_c[i])
{
for (j; s[j] != min_c[i] && j < n; j++)
t[++topt] = s[j];
u[++top_u] = min_c[i];
j++;
}
else
u[++top_u] = t[topt--];
}
while (topt != -1)
u[++top_u] = t[topt--];
cout << u << endl;
return 0;
}