UVa 11988

题意

破碎的键盘(又名 悲剧文本)

你有一个破损的键盘。键盘上的所有键都可以正常工作,但有时Home键或者End键会自动按下。你并不知道键盘存在这一问题,而是专心地打稿子,甚至连显示器都没打开。当你打开显示器之后,展现在你面前的是一段悲剧的文本。你的任务是在打开显示器之前计算出这段悲剧文本。
输入包含多组数据。每组数据占一行,包含不超过100000个字母、下划线、字符“[”或者“]”。其中字符“[”表示Home键,“]”表示End键。输入结束标志为文件结束符(EOF)。输入文件不超过5MB。对于每组数据,输出一行,即屏幕上的悲剧文本。

思路

一开始理解错了题意, 还以为是类似于括号平衡还用栈做
后来发现是[]内部的要先输出,在紫书的提示下采用链表

向量和数组的优势是可以随机的存取元素和在末尾添加删除元素,而当插入元素时,需要移动大量的数据,消耗大量的时间。而链表的优势是可以在O(1)删除和插入数据。所以在频繁移动元素时,可以使用链表

为了方便起见,假设字符串s的最前面还有一个虚拟的s[0],则next[0]就可以表示显示屏中最左边的字符。再用一个变量cur表示光标位置:即当前光标位于s[cur]的右边。cur=0说明光标位于“虚拟字符”s[0]的右边,即显示屏的最左边。
提示:为了方便起见,常常在链表的第一个元素之前放一个虚拟结点为了移动光标,还需要用一个变量last表示显示屏的最后一个字符是s[last]
头结点只是起到一个标记的作用,不表示真实的位置。

链表中的头结点总是指向链表的第一个元素。然后开始插入元素。

当所有元素插入完毕后,只需要从头结点开始,顺着next数组即可按顺序输出整个链表。

链表

指针的链表实现方式是 : 当前节点的next指向下一个节点
用数组模拟就是 :

for(int i = next[0]; i != 0; i = next[i])

AC代码

#include <stdio.h>
#include <string.h>
#define maxn 100000 + 100

char s[maxn];
int next[maxn];

int main()
{
    int i, len;
    int last, cur;
    while( ~scanf("%s",s+1) ){
        len = strlen(s+1);
        last = 0, cur = 0;
        next[0] = 0;
        for( i = 1; i <= len; i++ ){
            if( s[i] == '[' )   cur = 0;
            else if( s[i] == ']' )  cur = last;
            else{
                next[i] = next[cur];
                next[cur] = i;
                if( cur == last )   last = i;
                cur = i;
            }
        }
        for( i = next[0]; i != 0; i = next[i] )
            printf("%c",s[i]);
        putchar('
');
    }
}
原文地址:https://www.cnblogs.com/JinxiSui/p/9740621.html