String 문제여서 substring
메서드를 잘 쓰면 O(n)으로 통과할 수 있다고 생각함.
폭발 문자열 길이를 저장해놓고 이를 통해 인덱스를 제어하려고 했다.
사실 이게 3번째 시도인데, 1-2번째는 인덱스를 잘못 잡아서 인덱스 초과 런타임 에러 남.
아무튼 다 고치고 돌렸는데, 메모리 초과가 났다.
package solution;
import java.io.*;
public class BOJ9935_문자열폭발 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = br.readLine();
String bomb = br.readLine();
int len = bomb.length();
for (int i = 0; i <= str.length() - len; ) {
String tmp = str.substring(i, i + len);
if(tmp.equals(bomb)) {
// 같은 애들 삭제해준다,
str = str.replace(tmp, "");
// 인덱스를 현재 - len 으로 돌려서 다시 폭발 문자열이 생겼는지 체크
i = i - len < 0 ? 0 : i - len ;
} else {
// 같지 않다면 다음 문자 탐색한다
i++;
}
}
System.out.println(str.length() == 0 ? "FRULA" : str);
}
}
44% 에서 메모리초과 났다.
str = str.replace(tmp, "")
이 부분에서 str이 String 불변객체이기 때문에 계속 새로 메모리를 차지해서 날 수 있겠다.
그럼 메모리를 새로 저장하지 않는 StringBuilder
를 써봤다.
StringBuilder str = new StringBuilder(br.readLine());
String bomb = br.readLine();
int len = bomb.length();
for (int i = 0; i <= str.length() - len; ) {
String tmp = str.substring(i, i + len);
if(tmp.equals(bomb)) {
str.delete(i, i+len);
i = i - len < 0 ? 0 : i - len ;
} else {
i++;
}
}
ㅋㅋ 46%에서 시간초과 났다.
하암.. 문자열 메서드가지고 하면 안되는 문제같다.
도저히 모르겠어서 분류를 봤는데 스택이 있는거다.
엥 ?? 이게 어떻게 스택을 쓸 수 있지 생각해봤다.
문자열의 앞부터 한칸한칸 따지면서 푸는 문제는 스택을 떠올리라고 오답노트에 적어논 적 있다.
가장 마지막을 탐색하는 문제인가 이게 ..?
다른 사람의 풀이를 보았다.
stack.get(int idx)
를 통해서 bomb 길이만큼 비교하고, 맞으면 pop() 하고 아니면 넘어간다.
여기서 bombSize가 max 36이기 때문에 10^6 * 36 으로 O(n)
이 가능하다.
한번 처리를 진행한 스택 안에는 폭발 문자열이 존재하지 않는다.
처리 전에 문자열이 하나 push 되고 비교하는 순간 사라지기 때문이다.
그래서 스택의 맨 상단만 체크해주면 된다.
package solution;
import java.io.*;
import java.util.Stack;
public class BOJ9935_문자열폭발 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = br.readLine();
String bomb = br.readLine();
int len = bomb.length();
Stack<Character> stack = new Stack<>();
for (int i = 0; i < str.length(); i++) {
// 스택에 현재 문자를 넣는다.
stack.push(str.charAt(i));
// 스택 사이즈가 폭발 문자열보다 커지면, 가장 상단의 len만큼의 문자열을 비교하고 처리한다.
if(stack.size() >= len) {
boolean flag = true;
for (int j = 0; j < len; j++) {
if(stack.get(stack.size() - len + j) != bomb.charAt(j)) {
flag = false;
break;
}
}
if(flag) {
for (int j = 0; j < len; j++) {
stack.pop();
}
}
}
}
StringBuilder ans = new StringBuilder();
for(Character c : stack) {
ans.append(c);
}
System.out.println(ans.length() == 0 ? "FRULA" : ans);
}
}
스택에 get 메서드를 처음 써본다.
효율적인 코드가 아니라고 생각했는데 시간, 메모리 측면에서는 확실하게 적은 비용으로 관리할 수 있다.
문자열 문제에서 비교하는 문제는 스택도 떠올려보기..