首页 > 代码库 > UVa11988 Broken Keyboard(悲剧文本)

UVa11988 Broken Keyboard(悲剧文本)

UVa11988 Broken Keyboard(悲剧文本)

题目链接:UVa11988
题目描述:
输入包含多组数据,每组数据占一行,包含不超过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保存“光标位置”,这样输入一个字符相当于在数组中插入一个字符,这样就需要先把后面的字符全部右移,给新的字符填出位置
由上面分析,我们可以知道,这样就非常复杂了,会超时间
所以我们考虑用链表(linked list)
方便起见,常常在链表的第一个元素之前放一个虚拟结点。
每输入一个字符就把它存起来,设输入字符串是s[1~n],则可以用next[i]表示在当前显示屏中s[i]右边的字符编号。
假设字符串s的最前面还有一个虚拟的s[0],则next[0]就可以表示显示屏中最左边的字符,再用一个变量cur表示光标的位置,即当前光标位于s[cur]的右边,cur=0说明光标位于虚拟字符是s[0]的右边,即显示屏的最左边,为了移动光标,还需要用一个变量last表示显示屏的最后一个字符s[last]
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
参考代码:

//破损的键盘.cpp
#include<iostream>
#include<string>

using namespace std;
const int maxn = 100000 + 5;
int last, cur, next[maxn]; 
char s[maxn];

int main()
{
    while(cin >> s+1)
    {
        int n = strlen(s+1);
        last = cur = 0;
        next[0] = 0;

        for(int i = 1;i <= n;i++)
        {
            char ch = s[i];
            if(ch == ‘[‘)cur = 0;
            else if(ch == ‘]‘)cur = last;
            else
            {
                next[i] = next[cur];
                next[cur] = i;
                if(cur == last)
                    last = i;//更新“最后一个字符”编号
                cur = i;//移动光标
            }
        }

    for(int i = next[0]; i != 0; i = next[i])
        cout << s[i]; //这里将[光标cur放入0的位置
    cout << endl;
    }
    return 0;
}

调试分析:
测试数据:

 This_is_a_[Beiju]_text


我们可以分析道显示程序中,next[0] = 12那么i = next[12] = 13所以s从s[13]开始显示。