题意
破碎的键盘(又名 悲剧文本)
你有一个破损的键盘。键盘上的所有键都可以正常工作,但有时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('\n');
}
}