[UVA]11988 - Broken Keyboard (a.k.a. Beiju Text) 题解 及一点点感想

前言

暑期小组开始了每日一题模式,我对ACMer or 算法题 一直是很膜拜的,,,然而自己及其不喜欢做题,,,(可能是大一时的阴影。。)但是就像@Jung学长说的,手上功夫不能放松,这个暑假每天也是逼着自己写题。。。

某天聊天时 @pangda 同学说的一句话倒是挺让我信服的,我感觉挺符合我自己的,即在算法题的时间和内存限制下让我们更多的去考虑优化和效率,一般人都能实现功能,但是更高效的代码却少有人能做到。

今天在做这道题时更切身感受到了,于是记录下,也算是勉励自己。

正文

原题链接

中文版题目

Description

WJL同学的键盘出现了奇妙的故障,所有键都会正常的工作,但是键盘上的Home以及End键有时候会莫名其妙的自己按下。但是盲打很熟练的他一般习惯关闭显示器打字,因为这样很酷。

现在他正在打一段文本,假设你已经知道这段文本以及Home和End键会什么时候出现故障自行按下。请你编写一个程序,求出他最后打出的文本。

Input

输入数据有多组。

每组数据在一行内包含了至多100000个字母、下划线和两个特别的标点’[‘以及’]’,其中’[‘代表输入到此时”Home”键会被按下。而’]’则代表输入到此时”End”键会被按下。
输入数据以EOF作为结束,并且我们保证输入数据的大小不超过5MB。

Output

对于每组数据,请在一行之内输出最后他打出的文本是怎样的。

Sample Input

This_is_a_[Sample]_text
[[]][][]Nihao_I_am_a_Sample_Input
This_pr[oblem_has_a_100]0[m]s_time_limit
Maybe_theres_no_bracket

Sample Output

SampleThis_is_a__text
Nihao_I_am_a_Sample_Input
moblem_has_a_100This_pr0s_time_limit
Maybe_theres_no_bracket

Hint

①题目数据量较大,请C++考虑使用读入优化或者scanf/gets。
②本题不宜采用在数组中挪动字母的方式,你可以认为一定会超时。
③提示:可以尝试使用”链表“或者”双向队列“来解决这个问题

解决方法( Low )

#include <iostream>
#include <list>
using namespace std;
int main(void)
{
    list<string> res;
    string line;
    bool end = false;
    bool home = false;
    while(cin >> line){
        auto it = line.begin();
        auto head = it;
        auto tail = line.end();
        while(1){  
            while(it != tail && *it != '[' && *it != ']' )
                it++;
            if(home)
                res.push_front(string(head, it));
            else
                res.push_back(string(head, it));
            home = end = false;
            if(it == tail){
                for(auto i : res)
                    cout << i ;
                cout << endl;
                res.clear();
                break;
            }
            if(*it == '[')
                home = true;
            else 
                end = true;
            it++;
            head = it;
        }

    }
}

在哪里可以优化呢???

我自己不是ACMer,但是之前听说过对于std::cin可以这样提速
cin.sync_with_stdio(false);
原因。。。我还不太懂,日后补上。

还可以更加优化嘛???

最近一直在学习C++11,所以第一反映就是对于std::list 的插入,我们可以使用std::move减少一次临时对象的拷贝构造和析构。即

if(home)
    res.push_front(std::move(string(head, it)));
else
    res.push_back(std::move(string(head, it)));

三次结果对比

结果

三次AC的耗时不同,130ms的就是我们的Low版,而对std::cin提速之后直接降到了60ms,而使用了std::move又减少了10ms.

感想

其实可能还能继续优化,我也不是ACMer,就不深入探索了,但是这题给我的感触很深,从上来说,C++11和C++的各种优化值得我们学习并且深入实践,从上来说, 成为TOP的路上不光需要基础的知识,更需要一颗不断思考不断进取的心,每行代码都做的更好,哪怕是更好一点点!

fin

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值