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循环会直接退出,之后下一轮就可以按顺序建立链表,初次学习可能会比较模糊,多思考,多尝试,一定可以理解这个过程

posted @ 2020-09-19 01:34  徒手拆机甲  阅读(133)  评论(0)    收藏  举报