【题意】一个括号序列,你有以下三种操作:"L"光标左移;"R"光标右移;"D"删掉这个括号以及和它对应的括号之间的所有括号,并且把光标移动到被删后右边的那个括号上。如果没有了,就移动到串的末尾。现在给你原括号序列和操作,求最终结果!
【分析】由于操作最多有50万个,那么简单想一下用链表来暴力模拟都是能过得去的。那么,我在这里用了类似于跳转链表来模拟这个过程!但是这里我并不是一个一个的跳转的,而是预处理了最大的括号匹配,直接跳转到可以到达的最大位置,这样就更快的完成删除这个过程了!具体实现,见下面的代码!
【AC代码】
#include <stdio.h>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn = 500010;
char s[maxn],q[maxn];
int l[maxn],r[maxn],pos[maxn];//l,r分别来表示左移和右移
int S[maxn];
int main(){
int n,m,p,top=0;
cin>>n>>m>>p;
cin>>s>>q;
//INIT.
for(int i=1; i<=n; i++){
l[i]=i-1,r[i]=i==n?0:i+1;
if(s[i-1]=='('){
S[++top] = i;
}else{
pos[S[top]] = i;//记录左括号对应的右括号位置
pos[i] = S[top--];//记录右括号对应的左括号
}
}
//UPdate And Query.
for(int i=1; i<=m; i++){
if(q[i-1]=='L') p = l[p];
else if(q[i-1]=='R') p = r[p];
else{
if(s[p-1]==')') p = pos[p];//向左的话就要直接访问pos[p],向右则不用转换!
//合并区间
l[r[pos[p]]] = l[p];//清除匹配的括号-->
r[l[p]] = r[pos[p]];//清除匹配的括号<--
p = r[pos[p]]==0?l[p]:r[pos[p]];
}
}
while(l[p]) p=l[p];//找到最左边的括号的位置
while(p){
cout<<s[p-1]<<"";
p = r[p];
}
return 0;
}