티스토리 뷰
[Java+Python]9935번, 문자열 폭발
Vagabund.Gni 2023. 7. 17. 00:04목차
문제
상근이는 문자열에 폭발 문자열을 심어 놓았다.
폭발 문자열이 폭발하면 그 문자는 문자열에서 사라지며, 남은 문자열은 합쳐지게 된다.
폭발은 다음과 같은 과정으로 진행된다.
- 문자열이 폭발 문자열을 포함하고 있는 경우에, 모든 폭발 문자열이 폭발하게 된다.
- 남은 문자열을 순서대로 이어 붙여 새로운 문자열을 만든다.
- 새로 생긴 문자열에 폭발 문자열이 포함되어 있을 수도 있다.
- 폭발은 폭발 문자열이 문자열에 없을 때까지 계속된다.
상근이는 모든 폭발이 끝난 후에 어떤 문자열이 남는지 구해보려고 한다. 남아있는 문자가 없는 경우가 있다. 이때는 "FRULA"를 출력한다.
폭발 문자열은 같은 문자를 두 개 이상 포함하지 않는다.
입력
첫째 줄에 문자열이 주어진다. 문자열의 길이는 1보다 크거나 같고, 1,000,000보다 작거나 같다.
둘째 줄에 폭발 문자열이 주어진다. 길이는 1보다 크거나 같고, 36보다 작거나 같다.
두 문자열은 모두 알파벳 소문자와 대문자, 숫자 0, 1,..., 9로만 이루어져 있다.
출력
첫째 줄에 모든 폭발이 끝난 후 남은 문자열을 출력한다.
풀이
스택 2 단계의 첫 문제이다. 그러나 이번 문제에선 직접 스택이나 어레이덱을 사용하지 않는다.
이 문제는 지정된 '폭발 문자열'을 찾아 제거하는 문제이다.
입력으로 주어진 문제에서 '폭발 문자열'이 더 이상 존재하지 않을 때까지 해당 문자열을 반복해서 제거한다.
이를 위해 스택 자료구조를 사용할 수도 있지만, 여기선 char[] 배열을 스택처럼 사용하기로 한다.
문제 풀이를 요약하면 매우 간단한데, 스택에 문자를 추가하고 각 단계에서 폭발 문자열인지 검사한다.
이 과정을 모두 마치고 스택에 남아있는 문자가 답이 된다.
항상 말로만 알고리즘을 설명하려니 쉽지 않았는데, 이번 글부터는 코드 조각을 사용해서 적어보려고 한다.
코드를 구성하는 알고리즘은 아래와 같다.
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
char[] text = br.readLine().toCharArray();
char[] explosion = br.readLine().toCharArray();
char[] result = new char[text.length];
int idx = 0;
주어진 입력의 첫 줄을 text, 두 번째 줄을 explosion이라는 이름의 char[]로 변환한다.
또한 결과를 저장할 배열 result와 idx를 초기화한다. 여기서 idx는 result 배열에서 현재 채워 넣은 부분,
그러니까 가장 마지막 부분의 인덱스를 가리키게 된다.
for (char c : text) {
result[idx] = c;
향상된 for문을 이용해서 text의 각 문자 c를 result 배열의 idx 인덱스에 저장한다.
이 부분이 스택의 push와 같은 역할을 한다.
if (isExplosive(result, explosion, idx)) {
idx -= explosion.length;
}
idx++;
}
이어서 isExplosive 메서드를 호출해서 방금 추가된 부분이 폭발 문자열과 일치하는지 검사한다.
만약 일치한다면 idx를 폭발 문자열의 길이만큼 감소시킨다. 이 부분은 요소를 pop 하는 것과 동일하다.
일치하지 않는다면 idx를 1 증가시킨다.
isExplosive는 다음과 같이 구현된다.
private static boolean isExplosive(char[] result, char[] explosion, int idx) {
if (idx < explosion.length - 1) {
return false;
}
for (int i = 0; i < explosion.length; i++) {
if (explosion[i] != result[idx - explosion.length + 1 + i]) {
return false;
}
}
return true;
}
우선 result, explosion, idx를 매개변수로 받는다.
if (idx < explosion.length - 1) {
return false;
}
이어서 idx가 폭발 문자열의 길이보다 작은 경우, 즉 result 배열의 길이가 폭발 문자열의 길이보다 작은 경우
폭발 문자열과 일치할 가능성이 없기 때문에 false를 반환한다.
for (int i = 0; i < explosion.length; i++) {
if (explosion[i] != result[idx - explosion.length + 1 + i]) {
return false;
}
}
그렇지 않다면 result배열의 마지막 부분과 폭발 문자열을 한 글자씩 비교한다.
일치하지 않는 문자가 있다면 폭발 문자열이 아니므로 false를 반환한다.
return true;
}
이를 통과하고, 모든 문자가 일치한다면 true를 반환한다. 이는 현재까지 추가된 문자열의 마지막 부분이
폭발 문자열과 일치한다는 의미이다.
System.out.println(idx == 0 ? "FRULA" : String.valueOf(result, 0, idx));
모든 과정이 끝나면 idx가 0인지 판별한다.
만약 0이라면 "FRULA"를 출력하고, 그렇지 않다면 result배열에서 idx까지의 요소를 출력한다.
스택에 남아있는 요소를 전부 출력하는 것이라고 생각할 수 있다.
Java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
char[] text = br.readLine().toCharArray();
char[] explosion = br.readLine().toCharArray();
char[] result = new char[text.length];
int idx = 0;
for (char c : text) {
result[idx] = c;
if (isExplosive(result, explosion, idx)) {
idx -= explosion.length;
}
idx++;
}
System.out.println(idx == 0 ? "FRULA" : String.valueOf(result, 0, idx));
}
private static boolean isExplosive(char[] result, char[] explosion, int idx) {
if (idx < explosion.length - 1) {
return false;
}
for (int i = 0; i < explosion.length; i++) {
if (explosion[i] != result[idx - explosion.length + 1 + i]) {
return false;
}
}
return true;
}
}
Python
import sys
text = list(sys.stdin.readline().rstrip())
explosion = list(sys.stdin.readline().rstrip())
result = [0 for _ in range(len(text))]
idx = 0
def isExplosive(result, explosion, idx):
if idx < len(explosion) - 1:
return False
for i in range(len(explosion)):
if explosion[i] != result[idx - len(explosion) + 1 + i]:
return False
return True
for c in text:
result[idx] = c
if isExplosive(result, explosion, idx):
idx -= len(explosion)
idx += 1
print("FRULA" if idx == 0 else "".join(result[:idx]))
Performance
'Algorithm > [Java+Python+JavaScript]BackJoon' 카테고리의 다른 글
[Java+Python]1725번, 히스토그램 (0) | 2023.07.21 |
---|---|
[Java+Python]17299번, 오등큰수 (1) | 2023.07.20 |
[Java+Python]17298번, 오큰수 (0) | 2023.07.18 |
[Java+Python]7579번, 앱, 냅색문제 (0) | 2023.07.16 |
[Java+Python]2629번, 양팔저울 (0) | 2023.07.14 |
[JavaScript]2941번, 크로아티아 알파벳, 좀 더 어려운 문자열 다루기 (1) | 2023.07.12 |
- Total
- Today
- Yesterday
- 여행
- 스트림
- 지지
- Algorithm
- Backjoon
- 남미
- 유럽
- 칼이사
- spring
- 중남미
- 기술면접
- a6000
- 세계여행
- java
- 면접 준비
- 세계일주
- 야경
- Python
- 동적계획법
- BOJ
- 백준
- 유럽여행
- RX100M5
- 맛집
- 알고리즘
- 리스트
- 파이썬
- 스프링
- 세모
- 자바
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |