https://ac.nowcoder.com/acm/contest/11164/C
题目描述
小 L 发明了一个文本编辑器,由于小 L 非常垃圾,所以写出的文本编辑器也很垃圾。 该文本编辑器的运行方式大概是这样的:一开始文本为空,有一个光标在开头,每一次小 L 会输入一个字符,该字符就会被插入到光标的位置上,然后光标会随机地停留在该字符的左边或右边。 现在小 L 用这个文本编辑器打了一大段文字,但他却忘了保存了,他只记得他依次打了哪些字符和打完每个字符后光标停在了该字符的左边还是右边,你能帮助他还原出最终文本的内容吗?
输入描述:
输入文件有两行,第一行为一个字符串s,第二行为一个字符串t。
s, t 的长度相同,s 为一个仅包含小写字母的字符串,t 为一个仅包含’L’, ‘R’ 的字符串。分别表示小 L 依次打了哪些字符,和每打完一个字符后光标停在了字符的左边还是右边( ‘L’ 为左边,‘R’ 为右边)。
输出描述:
输出仅一行一个字符串,为最终文本的内容。
示例1
输入
abcde
LLRLR
输出
cedba
说明
在每一时刻文本编辑器的状态如下("|"表示光标的位置):
|a
|ba
c|ba
c|dba
ce|dba
设 n 为 s, t 的长度。
对于 30%30% 的数据,满足n≤1000。
另有 20%20% 的数据,满足存在一个 x 使得x < n,t_0 = t_1 = …t_x = ‘R’, t_{x + 1} = … = t_{n - 1} = 'L’0≤x<n。
对于 100% 的数据,满足 1≤n≤1,000,000。
一、模拟链表
#include<iostream>
using namespace std;
struct node{
int r,l;
};
const int maxn = 1e6+5;
node res[maxn];
int main()
{
string s,t;
cin>>s>>t;
for(int i=0;i<=s.length();i++){
res[i].l = -1,res[i].r = maxn;
}
for(int i=0;i<s.length()-1;i++){
if(t[i] == 'L'){
if(res[i].l != -1) res[res[i].l].r = i+1;
res[i+1].l = res[i].l;
res[i].l = i+1;
res[i+1].r = i;
}else{
if(res[i].r != maxn) res[res[i].r].l = i+1;
res[i+1].r = res[i].r;
res[i+1].l = i;
res[i].r = i+1;
}
}
int first = -1;
for(int i=0;i<s.length();i++){
if(res[i].l == -1){
first = i;
break;
}
}
int final = first;
while(res[final].r != maxn){
cout<<s[final];
final = res[final].r;
}
cout<<s[final]<<endl;
}
二、前后缀
转自https://blog.nowcoder.net/n/28aa5a550c0841c7831eb4b8f30057ed?f=comment
发现每次操作完之后,光标前的字符串就永远是这个字符串的前缀了,光标后永远是这个字符串的后缀了。
因为无论光标在当前字母的左边还是右边,都不可能影响到上一个字符和上上个字符之间的东西(后缀同理)。
所以开两个 string 记一下当前光标前的字符串和光标后的字符串。
发现光标后的字符串需要从前面插入字符,string好像不支持,就从后插入,最后再反过来。
#include <iostream>
#include <algorithm>
using namespace std;
string a,b,x,y;//x后缀,y前缀
int main() {
cin >> a >> b;
int n=a.size();
for(int i=0;i<n;i++)
{
if(b[i]=='L') x+=a[i];//放到左边相当于后缀多了个a[i]
else y+=a[i];//右边相当于前缀多了个a[i]
}
reverse(x.begin(),x.end());//后缀要反过来
cout << y << x;
return 0;
}