Broken Keyboard--又名悲剧文本(线性表)

 题目:

你有一个破损的键盘。键盘上的所有键都可以正常工作,但有时Home键或者End键会自 动按下。你并不知道键盘存在这一问题,而是专心地打稿子,甚至连显示器都没打开。当你 打开显示器之后,

展现在你面前的是一段悲剧的文本。你的任务是在打开显示器之前计算出 这段悲剧文本。 输入包含多组数据。每组数据占一行,包含不超过100000个字母、下划线、字符“[”或 者“]”。其中字符“[”表示Home键,

“]”表示End键。输入结束标志为文件结束符(EOF)。输 入文件不超过5MB。对于每组数据,输出一行,即屏幕上的悲剧文本。 

样例输入: 
This_is_a_[Beiju]_text 
[[]][][]Happy_Birthday_to_Tsinghua_University

样例输出: 
BeijuThis_is_a__text 
Happy_Birthday_to_Tsinghua_University

分析与解答:

本题是用两个数组来模拟表示顺序线性表。

这是书上给出的思路:最简单的想法便是用数组来保存这段文本,然后用一个变量pos保存“光标位置”。这样,输入一个字符相当于在数组中插入一个字符(需要先把后面的字符全部右移,给新字符

腾出位置)。很可惜,这样的代码会超时。为什么?因为每输入一个字符都可能会引起大量字符移动。在极端情况下,例如,2500000个a和“[”交替出现,则一共需要0+1+2+…+2499999=6*1012次

字符移动。解决方案是采用链表(linked list)。每输入一个字符就把它存起来,设输入字符串是s[1~n],则可以用next[i]表示在当前显示屏中s[i]右边的字符编号(即在s中的下标)。

使用了一个next数组来进行位置索引,用cur和last变量来记录字符串删除起始点和终止点。最后输出由i=Next[0]开始,i==0时作为停止条件,i = Next[i]作为每次循环的刷新。

0.为了方便起见,常常在链表第一个元素之前放一个虚拟节点s[0] 
1.光标 cur,最后一个字符编号 last,其实只是由于这题 home,end的条件限制 
如果用数组建立单链表,只需要 next[i]和s[i] 
2.其中 next[i]是s[i]连的下一个字符的编号,比如: 
s[0],next[0]=3连下一个字符-> 
s[next[0]],next[next[0]] 
3.在本题中,如果next[i]=0,说明不知道这个节点连哪个下一个节点,如果全部插入完节点,遇到next[i]=0,就意味着这个链表已经结束 
所以有如下对链表遍历的方法:

for(int i=next[0];i!=0;i=next[i])
      printf("%c",s[i]);

4.下面说说怎么插入 
s[i]对应一个next[i],那么s[i]下一个连的是s[next[i]],next[next[i]] 
如果在s[i]后面插入s[j]next[j] 
只需next[j]=next[i],next[i]=j 
新节点j先插到后面next[i]的前面,再把前面i的后面连的那个节点改为新插入的那个j 
5.再来说说本题 
a.只需改变s的输出顺序,输出s[next[i]] 
b.多了个[],就是说插入的位置会发生变化,怎么办? 
光标派上用场, 
先看一般情况:s[0]0a1b2c3,注意光标的意思,假设光标一开始是0,你输入a,那1就是此时光标的位置,假设s[1]=a,那我们还没遍历到b的时候,next[1]=0(看不懂得话看上面的黑色重点字体),next[0]=1,

这是在s[0]后面插入s[1],(看不懂的话看重新看上面的4),此时如果光标等于最后一个字符的编号(比如last,cur初始值是0,那么你加了一个字符,最后一个字符编号自然需要更新)就更新最后一个字符编号,

然后把光标改成1 再看特殊的: 如果碰见[,光标跑到0了,把cur改成0 碰见],光标跑到最后一个了数的后面了,你们发现了吗,最后一个数的下标正好是光标的下标,所以cur=last 。

原理就是下图表示的样子??

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 #define maxn 100005
 5
 6 int cur, last, next[maxn];
 7 char s[maxn];
 8
 9 int main()
10 {
11     while(scanf("%s",s+1)==1)
12     {
13         int n = strlen(s+1);
14         cur = last = 0;
15         next[0] = 0;
16         for(int i = 1; i <= n; i++)
17         {
18             if(s[i]==‘[‘)
19                 cur = 0;         //光标移动到左端
20             else if(s[i]==‘]‘)
21                 cur = last;       //光标移动到右端
22             else
23             {
24                 next[i] = next[cur];
25                 next[cur] = i;
26                 if(cur == last)
27                     last = i;      //cur == last时文本长度增加
28                 cur = i;              //移动光标
29             }
30         }
31         for(int i = next[0]; i != 0; i = next[i])   将线性表输出
32             printf("%c",s[i]);
33         printf("\n");
34
35     }
36     return 0;
37 }

借鉴大佬博客:  https://blog.csdn.net/qq_40828914/article/details/81200011

        https://blog.csdn.net/gyh_420/article/details/70175276

        

原文地址:https://www.cnblogs.com/Dawn-bin/p/9498598.html

时间: 2024-07-31 04:57:20

Broken Keyboard--又名悲剧文本(线性表)的相关文章

Broken Keyboard(悲剧文本)

你有一个键盘,键盘上所有的键都能正常使用,只是Home键和End键有时会自动按下.你并不知道这一情况,而是专心地打稿子,甚至连显示器都没开电源.当你打开显示器之后,展现在你面前的是一段悲剧文本.你的任务是根据给出的键盘上实际输入的内容,计算并输出这段悲剧文本(即显示器上展现的文本) Input: 一行文本不超过1000000个字符,只包括字母.下划线.字符'['(表示Home键)和字符']'(表示End键盘). Output: 一个字符串,即符合题目描述的悲剧文本. Example: Input

UVa11988 Broken Keyboard(悲剧文本)

UVa11988 Broken Keyboard(悲剧文本) 题目链接:UVa11988 题目描述: 输入包含多组数据,每组数据占一行,包含不超过100000个字母.下划线.字符"["或者"]".其中字符"["表示Home键,"]"表示End键.输入结束标志为文件结束符(EOF)输入文件不超过5MB,对于每组数据,输出一行,即屏幕上的悲剧文本 样例输入: This_is_a_[Beiju]_text [[]][]Happy_B

UVA11988 Broken Keyboard (a.k.a. Beiju Text)【数组模拟链表】

Broken Keyboard (a.k.a. Beiju Text) You're typing a long text with a broken keyboard. Well it's not so badly broken. The only problem with the keyboard is that sometimes the "home" key or the "end" key gets automatically pressed (inter

11988 - Broken Keyboard (a.k.a. Beiju Text)

Broken Keyboard (a.k.a. Beiju Text) You're typing a long text with a broken keyboard. Well it's not so badly broken. The only problem with the keyboard is that sometimes the "home" key or the "end" key gets automatically pressed (inter

UVa 11988 - Broken Keyboard (a.k.a. Beiju Text) 题解

刘汝佳的题目,悲剧文本 -_-||| 这里使用vector<string>容器倒置记录数据,然后从后面输出就可以了. 难度就是不知道这样的文档到底哪里是开始输出,故此使用动态管理内存的容器比较好做. 增加了io处理的O(n)算法也没有上榜,郁闷. #include <stdio.h> #include <vector> #include <string> using std::vector; using std::string; const int MAX_

&lt;2014 05 16&gt; 线性表、栈与队列——一个环形队列的C语言实现

栈与队列都是具有特殊存取方式的线性表,栈属于先进后出(FILO),而队列则是先进先出(FIFO).栈能够将递归问题转化为非递归问题,这是它的一个重要特性.除了FILO.FIFO这样的最普遍存取方式外,还有一些扩展的数据结构,如双端队列.双栈.超队列.超栈等,它们是一种扩展与变异结构. 线性表有顺序存储和链接存储两类,这是针对计算机的线性存储空间作出的分类.前者可以是数组,后者可以是链表.字符串是线性表最常见的应用. 这里我用C语言实现了一个基于数组环形队列,它具有固定的队列空间.相比于链表实现,

B - Broken Keyboard (a.k.a. Beiju Text) 数组模拟链表

You're typing a long text with a broken keyboard. Well it's not so badly broken. The only problem with the keyboard is that sometimes the "home" key or the "end" key gets automatically pressed (internally). You're not aware of this iss

线性表---顺序表

线性结构的特点是:在非空的有限集合中,只有唯一的第一个元素和唯一的最后一个元素.第一个元素没有直接前驱元素,最后一个没有直接的后继元素.其它元素都有唯一的前驱元素和唯一的后继元素. 线性表是一种最简单的线性结构.线性表可以用顺序存储结构和链式存储结构存储,可以在线性表的任意位置进行插入和输出操作. 要想将线性表在计算机上实现,必须把其逻辑结构转化为计算机可识别的存储结构.线性表的存储结构主要有两种:顺序存储结构和链式存储结构. 线性表的顺序表示与实现 线性表的顺序存储结构 线性表的顺序存储结构指

数据结构 笔记2 线性表

线性表是最简单,最常用的一种数据结构,它是由n个数据元素(结点)组成的有限序列. 线性表的基本运算 1.置空表 InitList(L) ,构造一个空的线性表L 2.求表长 ListLength(L) ,返回线性表L中元素个数,即表长. 3.取表中第i个元素GetNode(L,i) ,若1 <= i <= ListLength(L) ,则返回第i个元素a[i] 4.按值查找LocateNode(L,x),在表L中查找第一个值为x的元素,并返回该元素在表L中的位置,若表中没有元素的值为x,则返回0