【题意】一个括号序列,你有以下三种操作:"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; }
时间: 2024-10-24 09:19:45