F - Transpose:
题目描述:
思路解析:
如果有一对括号,那么删掉括号对,并且将括号对里的字符串翻转,在翻转过程中,使字符串的字母改变大小写。那我们可以通过预处理找到每个括号对。
例如 A(x(AXB)x)B 我们可以发现 x(AXB)x 需要翻转一次并改变大小写,然后(AXB)翻转一次并改变大小写,那么相当于AXB不做变化。
所以我们预处理括号对后,我们顺序遍历这个字符串,如果碰到第一个括号对,那我们倒序遍历这个字符串,然后再次碰到下一个括号对后,那么再顺序遍历这个括号对的字符串。
那我们可以发现顺序遍历时,不用改变字符串大小写,倒序遍历时改变字符串大小写,那么这个处理就可以on完成。但是因为Java字符串处理实在太慢,on也被卡掉,所以推荐使用cpp处理字符问题。
代码实现:
#include <bits/stdc++.h>
using i64 = long long;
char change (char c){
if (islower(c)){
return std::toupper(c);
}else {
return std::tolower(c);
}
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::string s;
std:: cin >> s;
int n = s.size();
std:: vector<int> match(n,-1);
std:: vector<int> set;
for (int i = 0; i < n; ++i){
if (s[i] == '(') set.push_back(i);
else if (s[i] == ')'){
match[i] = set.back();
match[set.back()] = i;
set.pop_back();
}
}
std::string ans;
auto work = [&](auto &&self, int l, int r, bool st) -> void{
if (!st){
for (int i = l; i < r; ++i){
if (s[i] == '('){
self(self, i + 1, match[i], true);
i = match[i];
}else{
ans += s[i];
}
}
}else {
for(int i = r - 1; i >= l;--i){
if (s[i] == ')'){
self(self, match[i] + 1, i, false);
i = match[i];
}else {
ans += change(s[i]);
}
}
}
};
work(work, 0, n, false);
std::cout << ans << '\n';
return 0;
}