vua11988-题解
题干
你在输入文章的时候,键盘上的Home键和End键出了问题,会不定时的按下。你却不知道此问题,而是专心致志地打稿子,甚至显示器都没开。当你打开显示器之后,展现你面前的数一段悲剧文本。你的任务是在显示器打开前计算出这段悲剧的文本。 给你一段按键的文本,其中'['表示Home键,']'表示End键,输入结束标志是文件结束符(EOF)。
输入
This_is_a_[Beiju]_text
[[]][][]Happy_Birthday_to_Tsinghua_University、
输出
BeijuThis_is_a__text
Happy_Birthday_to_Tsinghua_University
分析
按下[,在字符串开头插入,按下],在字符串末尾插入,由于有大量的插入换位置操作,显然用链表储存较好。手写数据结构里面的链表太慢了,我们考虑用数组模拟链表
我们通常用
value[i]表示i点储存的值
next[i] 储存的值是下一个目标值的索引,即i下一个的值是value[next[i]]
idx 索引,一个一个往前走。这玩意是线性的,只是由于next才有了链表那样跳跃的效果
来模拟链表
注意! 我们理解这个结构不要按照数组的数据结构来理解,要按照链表的结构来理解,否则容易搞混
代码
具体思路,由于有现成的字符串,我们不需要value,只需要next[],对于每个字符,用next指向它下一个字符就可以了
注意我们用ne[0]表示头节点,这个指向-1,具体插入逻辑的话,无论是在开头还是结尾还是正常中间都是一样的
让现在的ne[i]指向光标p指向的位置,然后光标p指向i,最后更新p为i(光标走到i这里了)
最后更新behind,即末尾处,如果触发]逻辑或者一直在末尾处加字符,(behind==p)就让behind走向现在光标i这里
#include<iostream>
#include<string>
using namespace std;
const int MAXN=100010;
int ne[MAXN];
int main(){
string arr;
while(getline(cin,arr)){
int len=arr.size();
int p=0,behind=0;
//用behind表示最后一个字符的位置,让ne指向-1表示没有数了
ne[0]=-1;
for(int i=0;i<len;i++){
if(arr[i]=='['){
p=0;
}
else if(arr[i]==']'){
p=behind;
}
else{
//无非就是考虑ne[]怎么变,p和behind怎么变
//ne[i]指向ne[p]原来指向的索引,然后被ne[p]插入
//p要被更新为i,即新插入的那个,为光标所在处
ne[i+1]=ne[p];
ne[p]=i+1;
if(behind==p)behind=i+1;
p=i+1;
}
}
for(int i=ne[0];i+1;i=ne[i])printf("%c",arr[i-1]);
cout<<endl;
}
return 0;
}

浙公网安备 33010602011771号