문자열 S가 주어졌을 때, 이 문자열에서 단어만 뒤집으려고 한다.
먼저, 문자열 S는 아래와과 같은 규칙을 지킨다.
- 알파벳 소문자('a'-'z'), 숫자('0'-'9'), 공백(' '), 특수 문자('<', '>')로만 이루어져 있다.
- 문자열의 시작과 끝은 공백이 아니다.
- '<'와 '>'가 문자열에 있는 경우 번갈아가면서 등장하며, '<'이 먼저 등장한다. 두 문자의 개수는 같다.
태그는 '<'로 시작해서 '>'로 끝나는 길이가 3 이상인 부분 문자열이고, '<'와 '>' 사이에는 알파벳 소문자와 공백만 있다. 단어는 알파벳 소문자와 숫자로 이루어진 부분 문자열이고, 연속하는 두 단어는 공백 하나로 구분한다. 태그는 단어가 아니며, 태그와 단어 사이에는 공백이 없다.
• 알파벳 소문자, 숫자, 공백, 특수 문자(<, >)로 이루어진 문자열 S에서 단어를 뒤집는 문제
• 태그: <로 시작해서 >로 끝나는 문자열, 사이에는 알파벳 소문자와 공백만 있음
• 단어: 알파벳 소문자와 숫자로만 이루어짐
• 단어와 단어 사이에는 공백 한 칸, 단어와 태그 사이에는 공백이 없음
• <open>tag<close> → <open>gat<close>
• <ab cd>ef gh<ij kl> → <ab cd>fe hg<ij kl>
• 단어뒤집기와 비슷하게 풀 수 있다.
• 태그 안인지 밖인지 구분해서 뒤집을지 말지 결정해야 한다. (태그 안->그대로, 태그 밖->뒤집기)
이 문제를 풀기위해서 모든 경우를 생각하면서 순서대로 코드를 작성하면 된다. 그리고 앞서 말한 조건을 체크 해주면서 처리해준다.
- 열린 태그(<)가 나오면 처음 시작이거나, 태그 안쪽 문자열의 끝이다.
- 닫힌 태그(>)가 나오면 마지막이거나, 태그 안쪽 문자열의 시작이다.
- 태그 안쪽/바깥쪽을 구분하여 안쪽이면 그대로 출력하고, 바깥쪽이면 뒤집어 출력 하기위해 스택에 넣는다. 그리고 다시 열린 태그(<)가 나오면 스택에서 꺼내면서 출력한다.
좀 더 구체적으로 이 과정을 나열해보면 다음과 같다.
#include <iostream>
#include <string>
#include <stack>
using namespace std;
void print(stack<char> &s) { // 스택에 있는 값을 모두 출력
while (!s.empty()) {
cout << s.top();
s.pop();
}
}
int main() {
string str;
getline(cin, str);
bool tag = false;
stack<char> s;
for (char ch : str) { // 문자열에서 한 문자씩 꺼내며 반복
if (ch == '<') { // 여는 태그가 나오면
print(s); // 스택에 값들을 모두 출력하고
tag = true; // 태그가 열렸다고 표시
cout << ch; // 태그 출력
} else if (ch == '>') { // 닫는 태그가 나오면
tag = false; // 태그가 닫혔다고 표시
cout << ch; // 태그 출력
} else if (tag) { // 태그가 열린상태라면
cout << ch; // 문자 '그대로' 출력
} else { // 태그가 닫힌상태라면
if (ch == ' ') { // 공백이 나오면
print(s); // 스택을 모두 출력
cout << ch; // 공백도 출력
} else { // 공백이 나오기 전까지는
s.push(ch); // 스택에 삽입
}
}
}
print(s); // 스택에 남은게 있다면 모두 출력
cout << '\n';
return 0;
}