StkOvflow

STACK OVERFLOW!

一言(ヒトコト)

UVA 11988 Broken Keyboard

原题Vjudge

题目大意

给定一个字符串,字符串中可能含有\([\)字符或者\(]\)字符
\([]\)框起来的字符串将会被移到最开头,(如果之前有过\([]\),则越晚出现的\([]\)内字符串会被放在越前面,输出最后得到的字符串

解题思路

解法1

用一个类似循环链表的东西存储这个字符串,\(cur\)代表的是光标的位置,\(last\)代表屏幕的最右边,遇到\(\ [\)就把\(cu\)r设为0,
遇到\(]\)就回到\(last\)的位置。
当前光标位于\(s[cur]\)的右边,\(ne[i]存的则是链表中i的下一个字符在s中的下标\)
如果\(ne[i] == 0\),代表超出了当前的屏幕上线,所以此时赋值\(last = i\)
每次插入完一个数不要忘记\(cur = i\),因为光标是会跟着插入的字符右移的

代码
#include <iostream>
#include <cstring>

using namespace std;

const int N = 1e5 + 10;
char s[N]; 
int cur, ne[N], last;

int main()
{
    while (cin >> s + 1) 
    {
        int len = strlen(s + 1);
        
        last = cur = ne[0] = 0;
        for (int i = 1; i <= len; i ++ ) 
        {
            char ch = s[i];
            if (ch == '[') cur = 0; //Home
            else if (ch == ']') cur = last; //End
            else {
                ne[i] = ne[cur], ne[cur] = i, cur = i; //插入一个字符
                if (ne[i] == 0) last = i; //屏幕边缘向右扩展
            }
        }
        for (int i = ne[0]; i; i = ne[i]) putchar(s[i]);
        puts("");
    }
    
    return 0;
}

解法2

用一个双端队列保存这个屏幕,遇到[键就设置flag = true,遇到]键设置flag = false;
对于一个字符,当flag = true , 插入到前面,否则插入到后面
这样对吗?
错的!!!!!!!!!!!!!

被[]框起来的字符串将会被移到最开头

所以这题我们只要遇到[就开始统计,将被[]框起来的字符串移到deque的队首,然后再把没被括号括中的字符串移到deque的队尾就好了
直接上代码

代码实现
#include <iostream>
#include <cstring>
#include <deque>

using namespace std;

int main()
{
    string str;
    while(cin >> str)
    {
        int len = str.size();
        deque<string> q;
        string S;
        bool flag = true;
        for(int i = 0; i < len; i ++ ) 
        {
            if (str[i] != '[' && str[i] != ']') S += str[i];
            else {
                flag ? q.push_back(S) : q.push_front(S);
                flag = (str[i] == ']'), S = "";
            }
        }
        flag ? q.push_back(S) : q.push_front(S);
        for (auto str : q) cout << str;
        cout << endl;
    }

    return 0;
}

时间

链表90ms,deque80ms

posted @ 2022-12-20 21:44  StkOvflow  阅读(40)  评论(0)    收藏  举报