에디터 [1406번 링크]

문제

한 줄로 된 간단한 에디터를 구현하려고 한다.
이 편집기는 영어 소문자만을 기록할 수 있는 편집기로, 최대 600,000글자까지 입력할 수 있다.

이 편집기에는 '커서'라는 것이 있는데, 커서는 문장의 맨 앞(첫 번째 문자의 왼쪽), 문장의 맨 뒤(마지막 문자의 오른쪽), 또는 문장 중간 임의의 곳(모든 연속된 두 문자 사이)에 위치할 수 있다. 즉 길이가 L인 문자열이 현재 편집기에 입력되어 있으면, 커서가 위치할 수 있는 곳은 L+1가지 경우가 있다.

이 편집기가 지원하는 명령어는 다음과 같다.

커맨드 설명
L 커서를 왼쪽으로 한 칸 옮김 (커서가 문장의 맨 앞이면 무시됨)
D 커서를 오른쪽으로 한 칸 옮김 (커서가 문장의 맨 뒤이면 무시됨)
B 커서 왼쪽에 있는 문자를 삭제함 (커서가 문장의 맨 앞이면 무시됨)
삭제로 인해 커서는 한 칸 왼쪽으로 이동한 것처럼 나타나지만, 실제로 커서의 오른쪽에 있던 문자는 그대로임.
P $ $라는 문자를 커서 왼쪽에 추가함.

초기에 편집기에 입력되어 있는 문자열이 주어지고, 그 이후 입력한 명령어가 차례로 주어졌을 때, 모든 명령어를 수행하고 난 후 편집기에 입력되어 있는 문자열을 구하는 프로그램을 작성하시오. 단, 명령어가 수행되기 전에 커서는 문장의 맨 뒤에 위치하고 있다고 한다.

접근방법

구현하는 모양은 위 그림같다고 생각하면 된다.
스택을 2개 사용해서 커서의 앞문자열, 뒷문자열을 만들어준다.
'|'를 커서라고 하면 위 그림은 '|abc' 와 같은 상태인 것이다.
그럼 커맨드를 어떻게 구현하면 될까?
커서는 가만히 있고 문자열을 이동시키는것으로 표현하면 된다.
그럼 아래와 같이 커맨드를 처리하는식이 된다.

커맨드 구현
L 커서의 왼쪽 스택에서 pop한 문자를 오른쪽 스택으로 push
D 커서의 오른쪽 스택에서 pop한 문자를 왼쪽 스택으로 push
B 커서의 왼쪽 스택에서 pop
P $ 커서의 왼쪽 스택에 $를 push

커맨드 입력이 끝났다.
이제 문자열을 출력해야할 차례다.
왼쪽 스택에서 pop한 문자열을 차례대로 오른쪽 스택에 push 해주면서 전부 비운다.
그런다음 오른쪽 스택에서 pop해서 문자열을 만들면 최종결과가 나오게 된다.

주의사항

Scanner를 사용해서 콘솔 입력을 받으면 시간초과에 걸리게 된다!
BufferedReader를 통해 입력을 받아야 시간초과에 걸리지 않고 성공할 수 있다.

추가로 알아볼 부분

  • 스택을 사용한 방법 말고 다른방법으로 구현해보기.
  • 왜 Scanner는 BufferedReader 보다 느릴까?

코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String inputText = br.readLine();
int numOfCommand = Integer.parseInt(br.readLine());
String[] commandArr = new String[numOfCommand];
for (int i = 0; i < numOfCommand; i++) {
commandArr[i] = br.readLine();
}
solution(inputText, commandArr);
}
public static void solution(String text, String[] commands) {
Stack<Character> leftOfCursor = new Stack<Character>();
Stack<Character> rightOfCursor = new Stack<Character>();
for (int i = 0; i < text.length(); i++) {
leftOfCursor.push(text.charAt(i));
}
for (String command : commands) {
if (command.charAt(0) == 'L') {
if (!leftOfCursor.isEmpty()) {
rightOfCursor.push(leftOfCursor.peek());
leftOfCursor.pop();
}
} else if (command.charAt(0) == 'D') {
if (!rightOfCursor.isEmpty()) {
leftOfCursor.push(rightOfCursor.peek());
rightOfCursor.pop();
}
} else if (command.charAt(0) == 'B') {
if (!leftOfCursor.isEmpty()) {
leftOfCursor.pop();
}
} else if (command.charAt(0) == 'P') {
leftOfCursor.push(command.charAt(2));
}
}
while (!leftOfCursor.isEmpty()) {
rightOfCursor.push(leftOfCursor.peek());
leftOfCursor.pop();
}
while (!rightOfCursor.isEmpty()) {
System.out.print(rightOfCursor.pop());
}
}

댓글

댓글을 사용할 수 없습니다.