UVA11988:悲剧文本(模拟链表)

时间:2022-06-06
本文章向大家介绍UVA11988:悲剧文本(模拟链表),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

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 issue, since you’re focusing on the text and did not even turn on the monitor! After you finished typing, you can see a text on the screen (if you turn on the monitor). In Chinese, we can call it Beiju. Your task is to find the Beiju text.

你在电脑上敲字,但是键盘是坏的,额,还不是特别坏,只是键盘有时候会自动按下Home键和End键。你敲字的时候没看显示器,光看手稿上的文字了。等你敲完整篇手稿,你发现杯具了......你需要找到那些错的文字。

Input There are several test cases. Each test case is a single line containing at least one and at most 100,000 letters, underscores and two special characters ‘[’ and ‘]’. ‘[’ means the “Home” key is pressed internally, and ‘]’ means the “End” key is pressed internally. The input is terminated by end-of-file (EOF). Output For each case, print the Beiju text on the screen.

Sample Input

This_is_a_[Beiju]_text

[[]][][]Happy_Birthday_to_Tsinghua_University

Sample Output

BeijuThis_is_a__text

Happy_Birthday_to_Tsinghua_University

概译:我们在用键盘输入字符串,如果出现' [ '光标就跳到最前面,如果出现' ] '就跳到最后面,给出输入时的字符串输出实际得到的字符串,详见样例。

思路:水题轻喷……模拟,链表插入,可以用数组实现模拟链表。我模拟链表不太熟,第一次是用STL模拟的。可以用一个双端队列deque储存最终结果,遇到一个' [ '就把后面的字符放在stack里,再遇到' [ '或' ] '时把stack里的字符放在deque的front里。PS:可能WA的数据:abc[123[456[ef

STL比较慢,100msAC

#include <bits/stdc++.h>
using namespace std;

int main()
{
    string s;
    while(getline(cin,s))
    {
        s+=']';
        deque<char>dq;
        stack<char>st;
        bool state=false;

        for (int i = 0; s[i]; ++i)
        {
            if (s[i]=='[')    state=true;    
            else if (s[i]==']')    state=false;

            if(state)   
            {
                if(s[i]!='[')    
                    st.push(s[i]);
                else
                    while(!st.empty())
                    {
                        dq.push_front(st.top());
                        st.pop();
                    }
            }
            else
            {
                if(s[i]!=']')
                    dq.push_back(s[i]);
                while(!st.empty())
                {
                    dq.push_front(st.top());
                    st.pop();
                }
            }     
        }

        while(!dq.empty())
        {
            printf("%c",dq.front());
            dq.pop_front();
        }
        printf("n");
    }
    return 0;
}

模拟链表是用一个next数组代替链表中的next指针,比如第一个字符s[1]的下一个是s[2],则next[1]=2。思想上和链表是一样的。另外众所周知,链表的题常常会把第0个作为不储存数据的辅助头结点,第一个下标才开始储存数据。

标程的思路是设置一个光标cur,但这个cur不是当前遍历到的位置i,而代表着位置i的字符应该插入在cur的右侧。期间cur有时会跳至左端即cur=0;有时要回到右端,所以还要开一个last变量保存最右端的下标,使cur=last跳回右端。

代码更精简,30ms,如下:

#include <bits/stdc++.h>
using namespace std;
#define maxl 100005

int main()
{
    char s[maxl];
    while(~scanf("%s",s+1))
    {
        int Next[maxl]={0};
        int cur=0,last=0;

        for (int i = 1; s[i]; ++i)
        {
            if(s[i]=='[')    cur=0;
            else if(s[i]==']')    cur=last;
            else
            {
                //链表插入操作
                Next[i]=Next[cur];
                Next[cur]=i;
                //last的更新
                if(cur==last)    last=i;
                //cur的更新
                cur=i;
            }
        }

        for (int i = Next[0]; i != 0; i = Next[i])
            if (s[i]!='['&&s[i]!=']')
                printf("%c",s[i]);
        printf("n");    
    }
    return 0;
}