문제
목표량
- 시간 제한: 1초
엘리스 토끼는 문자열을 직접 압축 해제하려고 합니다.
압축되지 않은 문자열 S가 주어졌을 때, 이 문자열 중 어떤 부분 문자열은 K(Q)와 같이 압축할 수 있습니다. 이것은 Q라는 문자열이 K 번 반복된다는 뜻입니다. K는 한 자릿수의 정수이고, Q는 0자리 이상의 문자열입니다.
예를 들면, 53(8)은 다음과 같이 압축을 해제할 수 있습니다.
53(8) = 5 + 3(8) = 5 + 888 = 5888
압축된 문자열이 주어졌을 때, 이 문자열을 다시 압축을 푸는 프로그램을 작성하세요.
지시사항
입력
- 첫째 줄에 압축된 문자열 S를 입력합니다.
- S의 길이는 최대 50입니다.
- 문자열은 (, ), 숫자로만 구성되어 있습니다.
출력
- 압축되지 않은 문자열의 길이를 출력합니다.
입력 예시
11(18(72(7)))
출력 예시
26
풀이
접근
이번 문제는 예외 상황을 고려해야 한다.
나올 수 있는 테스트 케이스를 생각해 보면
- 정상적으로 압축되어 있는 수들의 집합 ex) 53(8) = 5 + 3(8) = 5 + 888 = 5888(정답은 4)
- 괄호 없이 수만 나오는 경우 ex) 1111 = 1111(정답은 4)
- Q가 0자리 이상이므로 괄호 안에 아무것도 없는 상황 ex) 5() = 0(정답은 0)
이번 문제에서 입력을 받는 과정을 많이 고민했다.
가장 먼저 생각한 방법은
숫자만 push 후 pop해서 계산을 진행하는 방법이었는데, 테스트 케이스 2, 3번을 예외 처리하는 과정이 너무 복잡해서 구현하다 포기했다.
두 번째 방법은
문자열로 입력받아 하나씩 처리하는 방법이다.
뒤에서부터 확인하는 과정을 진행하고, 여는 괄호가 나올 때마다 계산을 진행하는 방식으로 구현하였다.
풀이
- 문자열을 입력받는다
- 뒤에서부터 숫자이면 Qn을 증가시킨다.
- 여는 괄호가 나오면 바로 앞 숫자와 Qn을 곱한다.
- 3번에서 사용한 숫자 앞의 숫자들은 더해야 하므로 다시 닫는 괄호가 나올 때까지 자릿수를 계산해 준다(Kn)
- Kn과 3번에서 구한 수를 더해준다.
- 3~5번 과정을 반복해 준다.
코드
더보기
#include <iostream>
#include <string>
using namespace std;
int main(void)
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int i, Qn, Kn;
int result = 0;
string S;
cin >> S;
i = S.size() - 1;
Qn = Kn = 0;
while (i >= 0)
{
if (isdigit(S[i]))
{
Qn++;
i--;
}
else if (S[i] == '(' && isdigit(S[i - 1]))
{
result = (S[i - 1] - '0') * Qn;
i -= 2;
while (i >= 0 && isdigit(S[i]))
{
Kn++;
i--;
}
result += Kn;
Kn = 0;
Qn = result;
}
else if (S[i] == ')')
{
i--;
}
}
if (Qn != result)
result += Qn;
cout << result;
return 0;
}
↑ 더 보기 클릭으로 펼치기
모범답안
더보기
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main() {
string input;
cin >> input;
vector<char> stack;
vector<int> depth_result(50, 0);
int depth = 0;
for (char ch : input) {
if (ch != ')') {
if (ch == '(') {
depth++;
depth_result[depth] = 0;
}
stack.push_back(ch);
} else {
for (int i = stack.size() - 1; i >= 0; --i) {
if (stack[i] == '(') {
int num = depth_result[depth];
for (int j = i + 1; j < stack.size(); ++j) {
num += 1;
}
depth--;
depth_result[depth] += num * (stack[i - 1] - '0');
stack.erase(stack.begin() + i - 1, stack.end());
break;
}
}
}
}
cout << depth_result[0] + stack.size() << endl;
return 0;
}
↑ 더 보기 클릭으로 펼치기
후기
문자열 다루는 기술이 많이 부족한 것 같다.
시간을 생각보다 너무 많이 써버려서 놀랐다.
'공부 > PS' 카테고리의 다른 글
엘리스 코드 챌린지 예선 [Day 4] 문제풀이 (0) | 2024.07.11 |
---|---|
엘리스 코드 챌린지 예선 [Day 2] 문제풀이 (0) | 2024.07.09 |
엘리스 코드 챌린지 예선 [Day 1] 문제풀이 (0) | 2024.07.08 |
[C++] 백준 21568번 (0) | 2024.04.07 |