uva11988 破损的键盘
问题描述:
你有一个破损的键盘。键盘上所有的键都可以正常工作,但有时候Home键或者End键会自动按下。你并不知道键盘存在这一问题,而是专心打稿子,甚至连显示器都没打开。当你打开显示器后,展现在你面前的是一段悲剧文本。你的任务是在打开显示器之前计算出这段悲剧文本。
输入包含多组数据。每组数据占一行,包含不超过100000个字母、下划线、字符“【”或者“】”。其中字符“【”表示Home键,“】”表示End键。输入结束标志为文件结束符(EOF)。输入文件不超过5MB。对于每组数据,输出一行,即屏幕上的悲剧文本。
样例输入:
This_is_a_[Beiju]_text
样例输出:
BeijuThis_is_a_text
题意也很简单,当你遇到home时,光标会回到起始位置,当你遇到end后光标重新回到后面,也就是【】内的内容会首置。所以这个问题可以用链表来模拟。如果要写链表,在算法竞赛中往往不使用指针写法,而是用next数组来完成这个指向工作。
简单来说next[i]的指表示i的下一个位置是什么地方。从next[0]开始指向链表开始,之后每个next都指向下一个next[]遍历链表的方式为for(int i=next[0];i!=0;I=next[i]) 就可以完整便利整个链表。在这道题中,我们需要先记录这个正常的链表顺序,随时更新光标位置和中止位置,直到遇到[将光标首置设置next[0]指向当前的字符位置,然后把next[当前字符]指向原先next[0]的位置;遇到]之后,让光标回归,也就是重新让链表从中止位置开始继续链接,在这个过程中,可以使用一些技巧来减小模拟难度。
#include<bits/stdc++.h>
using namespace std;
#define maxn 1000
int main()
{
int last,cur,next[maxn]; //last记录末位置,cur指向当前位置,next[]记录输出顺序
int i;
char s[maxn]; //输入字符串
while(scanf("%s",s+1)==1) //s[0]空出
{
last=cur=0;
next[0]=0;
for(i=1;i<=strlen(s+1);i++)
{
if(s[i]=='[') cur=0; //当输入]时,cur光标指向首位置,同时也可以让next[0]的值连接到当前的字符
else if(s[i]==']') cur=last; //当输入]时,cur光标指向上次所存储的末尾也就是上一个[出现之前
else //当读入其他字符时,插值操作
{
next[i]=next[cur];//正常情况下此时的cur比i要小一,在本段的意义为新的链表尾部就是之前的链表尾部,只不过之前的链表尾部现在要与i相连 ,在出现括号后可以让i的下一个与当前新光标产生关系
next[cur]=i;//该操作意义是把上一个值与现在连接起来
if(last==cur) last=i; //当末尾值和当前光标位置相同时,last和cur一样向i跟进
cur=i; //尾光标向后移动
}
}
for(i=next[0];i!=0;i=next[i])
cout<<s[i];
cout<<endl;
}
return 0;
}
例如输入abc[def]xyz
我们建立的链表应该如下所示
输入 a b c [ d e f ] x y z 下标 0 1 2 3 4 5 6 7 8 9 10 11 next的值 5 2 3 9 0 6 7 1 0 10 11 0
因为[ 和 ]的时候if循环会直接退出,之后下一轮就可以按顺序建立链表,初次学习可能会比较模糊,多思考,多尝试,一定可以理解这个过程

浙公网安备 33010602011771号