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

时间:2021-08-16 16:08:28

前言

暑期小组开始了每日一题模式,我对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)));

三次结果对比

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

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

感想

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

fin