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