UVA 11988 Broken Keyboard
题目大意
给定一个字符串,字符串中可能含有\([\)字符或者\(]\)字符
被\([]\)框起来的字符串将会被移到最开头,(如果之前有过\([]\),则越晚出现的\([]\)内字符串会被放在越前面,输出最后得到的字符串
解题思路
解法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

浙公网安备 33010602011771号