某一天,郭老师收到一封离奇的邮件,邮件内容为一大段的字符串文本(字符个数多达 100000 个),他完全看不懂这封邮件想表达什么意思,于是他找到一位密码学大神帮忙,为了留存神秘感,密码大神并没有告诉郭老师最终的答案,只告诉他要按照一些规则进行解密,首先开启两封空邮件 t 和 u,随后可进行两种操作:
- 在原始邮件内容 s 中,提取第一个字符,放到邮件 t 的末尾
- 在邮件 t 内,提取最后一个字符,放到邮件 u 的末尾
当邮件 s 和 t 均为空且邮件 u 中的内容字典序最小时,得到的 u 即为解密后的邮件。现在请你帮忙写程序解决此问题。
输入
输入包含多个测试用例,对于每个测试用例,输入一行非空的且全部由小写字母组成的邮件文本 s ( 1 ≤ |s| ≤ 100000 )。
输出
对于每个测试用例,输出一行解密后的邮件 u。
//AC 讨论区里朱杰大佬给的思路
//循环操作s数组,每次取出一个,加入到t数组的结尾,然后在对应记录字母个数的结构体里把这个字母的个数减一。
//然后判断t的结尾(也就是栈头元素),如果在s的后面还有比这个元素小的元素(这可不是扫一遍s数组,不然会t连妈妈都不认识的。
//注意了,就是扫一遍你的记录字母个数的那个结构体数组,从a扫到当前元素,如果中间有不是0的,
//那么就是成立,也就是要continue<就是接下来几句话),
//那么就continue,否则就进行下一步操作。
//那么,下一步怎么操作呢?老规矩,循环模拟栈的实现过程(看起来很高大上,其实就是个水一水的数组实现)。
//从t数组的尾部循环取元素,用我刚才说的方法判断,如果s后面有元素 比当前元素小,就直接弹出循环,否则就加入u数组,继续循环。
//这样,通过一条龙操作就可以把s数组中的所有字母全部放到t和u里面,然后就倒序输出t,顺序输出u就可以了。
#include<stdio.h>
#include<string.h>
int main()
{
int ch;
while (1)
{
char Str_S[100005] = { '\0' };
int S_len = 1;
int T_Num = 0;
int strmap[28] = { 0 };
//输入部分
ch = getchar();
if (ch < 0)
break;
Str_S[0] = ch;
strmap[ch - 'a']++;
for (int i = 1;; i++)
{
ch = getchar();
if (ch == 10)
break;
S_len++;
Str_S[i] = ch ;
strmap[ch - 'a']++;
}
//开始操作
char Str_T[100005] = { '\0' }, Str_U[100005] = { '\0' };
int ans = 0, xx = 0;
for (int i = 0;i<S_len; i++)
{
Str_T[T_Num++] = Str_S[i];
int kk = Str_S[i] - 'a';
strmap[kk]--;
for (int i = 0; i < kk; i++)
{
if (strmap[i] > 0)
{
ans = 1;
break;
}
}
if (ans == 1)
{
ans = 0;
continue;
}
for (int i = T_Num-1;i>=0; i--)
{
int kkk = Str_T[i] - 'a';
for (int i = 0; i < kkk; i++)
{
if (strmap[i] > 0)
{
ans = 1;
break;
}
}
if (ans == 1)
{
ans = 0;
break;
}
Str_U[xx++] = Str_T[i];
Str_T[i] = '\0';
T_Num--;
}
}
for (int i = 0; Str_U[i] != '\0'; i++)
printf("%c", Str_U[i]);
for (int i = T_Num - 1; i >= 0; i--)
printf("%c", Str_T[i]);
printf("\n");
}
return 0;
}