破损的键盘(又名:悲剧文本)(Broken Keyboard(a.k.a. Beiju Text), UVa 11988)
题目描述:
你有一个破损的键盘。键盘上所有的键都可以正常工作,但有时候Home键或者End键会自动按下。你并不知道键盘存在这一问题,而是专心打稿子,甚至连显示器都没打开。当你打开显示器后,展现在你面前的是一段悲剧文本。你的任务是在打开显示器之前计算出这段悲剧文本。
输入包含多组数据。每组数据占一行,包含不超过100000个字母、下划线、字符“[”或者“]”。其中字符“[”表示Home键,“]”表示End键。输入结束标志为文件结束符(EOF)。输入文件不超过5MB。对于每组数据,输出一行,即屏幕上的悲剧文本。
样例输入:
This_is_a_[Beiju]_text
[[]][][]Happy_Birthday_to_Tsinghua_University
样例输出:
BeijuThis_is_a_text
Happy_Birthday_to_Tsinghua_University
按下Home键光标会移到字符串开头,按下End键光标会移到字符串末尾,该题的基本思想是重组字符串,进行随机的插入的删除,所以要使用C++中的链表。
找出‘[’与‘]’之间的文字将其移到文字的最前面即可
因为这种操作涉及链表,可以直接用STL中的list
#include<bits/stdc++.h>
using namespace std;
int main()
{
string line;
while(getline(cin,line));
{
list<char> text;
auto i=text.end(); //i是迭代器,这个auto是类型
for(char c:line) //把line拆成单个字符
{
if(c=='[')
i=text.begin();
else if(c==']')
i=text.end();
else
{
i=text.insert(i,c);
++i;
}
}
for(char c:text)
putchar(c);
puts("");
}
return 0;
}
c++中的链表,适用于数组中元素大量移动
传统意义上的链表是用指针来实现的,c++使用不同的实现方法
当然,还有一种方法,后面补充
这里回忆一下list容器:
list.begin()
list.end()
list.empty()
list.size()
list.insert() //插入
list.erase()
list.sort() //特殊,需要用自己的排序方式,(这个不是algorithm里的)
list.reverse()
list.remove() //删除具有指定值的元素
...
#include<iostream>
#include<list>
using namespace std;
const int maxn=100003;
bool vis[maxn]; //判断是否已经被删除
list<int> stus;
list<int>::iterator pos[maxn]; //把迭代器存为数组
int main()
{
int n; //n个同学
cin>>n;
stus.push_front(1); //链表头插
pos[1]=stus.begin();
for(int i=2;i<=n;i++)
{
int k,p; //插到k同学旁边
//p为0或者1。若p为0,则表示将i号同学插入到k号同学的左边,p为1则表示插入到右边。
cin>>k>>p;
if(p==0)
{
pos[i]=stus.insert(pos[k],i);
//insert返回一个迭代器
//insert插入到选定位置的左边
}
else
{
list<int>::iterator it=pos[k];
//获得k同学位置的迭代器
++it; //向后移动
pos[i]=stus.insert(it,i);
}
}
int m; //去掉的同学的数量
cin>>m;
for(int i=0;i<m;i++)
{
int x;
cin>>x;
if(!vis[x]) //开始vis[i]=0
{
stus.erase(pos[x]);
//l.erase() 传参,传一个指针
vis[x]=true;
}
}
for(list<int>::iterator it=stus.begin();it!=stus.end();it++)
{
cout<<*it<<" ";
}
cout<<endl;
return 0;
}
/*
注意:l.insert(it,x) 插入到迭代器it 的左边
l.erase() 传参,传一个指针
*/