[1406] 에디터 | 백준 실버 2
🔎 문제설명
편집기에는 '커서'라는 것이 있는데, 커서는 문장의 맨 앞(첫 번째 문자의 왼쪽), 문장의 맨 뒤(마지막 문자의 오른쪽), 또는 문장 중간 임의의 곳(모든 연속된 두 문자 사이)에 위치할 수 있다. 즉 길이가 L인 문자열이 현재 편집기에 입력되어 있으면, 커서가 위치할 수 있는 곳은 L+1가지 경우가 있다.
이 편집기가 지원하는 명령어는 다음과 같다.
- L : 커서를 왼쪽으로 한 칸 옮김 (커서가 문장의 맨 앞이면 무시됨)
- D : 커서를 오른쪽으로 한 칸 옮김 (커서가 문장의 맨 뒤이면 무시됨)
- B : 커서 왼쪽에 있는 문자를 삭제함 (커서가 문장의 맨 앞이면 무시됨)
삭제로 인해 커서는 한 칸 왼쪽으로 이동한 것처럼 나타나지만, 실제 커서 위치는 그대로임- P $ : $라는 문자를 커서 왼쪽에 추가함
모든 명령어를 수행하고 난 후 편집기에 입력되어 있는 문자열을 구하는 프로그램을 작성하시오. 단, 명령어가 수행되기 전에 커서는 문장의 맨 뒤에 위치하고 있다고 한다.
입력
첫째 줄에는 초기에 편집기에 입력되어 있는 문자열이 주어진다. 이 문자열은 길이가 N이다.
둘째 줄에는 입력할 명령어의 개수를 나타내는 정수 M이 주어진다.
셋째 줄부터 M개의 줄에 걸쳐 입력할 명령어가 순서대로 주어진다.
출력
첫째 줄에 모든 명령어를 수행하고 난 후 편집기에 입력되어 있는 문자열을 출력한다.
제한사항
- 0 ≤ N ≤ 100,000
- 문자열은 영어 소문자로만 이루어져 있다.
- 1 ≤ M ≤ 500,000
- 명령어는 위의 네 가지 중 하나의 형태로만 주어진다.
🧪 자바 코드
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
LinkedList<Character> sL = new LinkedList<>();
LinkedList<Character> sR = new LinkedList<>();
//str.length <= 100,000
String str = br.readLine(); //스트링 입력
for(char c : str.toCharArray()){
sL.add(c);
}
//(1 ≤ M ≤ 500,000) 명령어수
int M = Integer.parseInt(br.readLine());
while(0 < M--){//sL.size()가 사실 상 커서위치이다.
char [] cmd = br.readLine().toCharArray();
if(cmd[0] == 'L' && !sL.isEmpty()) sR.push(sL.removeLast()); //왼쪽마지막->오른쪽첫번째로 이동
if(cmd[0] == 'D' && !sR.isEmpty()) sL.add(sR.pop()); //오른쪽첫번째->왼쪽마지막으로 이동
if(cmd[0] == 'B' && !sL.isEmpty()) sL.removeLast(); //왼쪽마지막 제거.
if(cmd[0] == 'P') sL.add(cmd[2]); //왼쪽마지막에 밀어넣기
}
while(!sL.isEmpty() || !sR.isEmpty()){//sL부터 출력 후 sR 출력
bw.write( !sL.isEmpty() ? sL.pop() : sR.pop());
}
bw.flush();
bw.close();
}
처음에 컬렉션을 하나만 써서 했는데 시간초과가 나서 두개를 이용해서 풀었습니다.
🧊 파이썬 코드
import sys
import collections as c
stack = c.deque(input()) #문자열 deque로
input() #명령어 수
C = len(stack) #커서위치
for cmd in sys.stdin:
if cmd[0] == 'P':
stack.append(cmd[2])
C += 1
if C and 'L' == cmd[0]:
stack.rotate(1)
C -= 1
if C and 'B' == cmd[0]:
stack.pop()
C -= 1
if cmd[0] == 'D' and C < len(stack):
stack.rotate(-1)
C += 1
stack.rotate(C)
print(''.join(stack)) #문자열로 변환
파이썬은 deque를 써서 시간복잡도를 줄일 수 있습니다.
커서가 항상 마지막을 가리키도록 rotate()를 사용합니다. 그리고 명령어가 끝나면 커서위치를 기준으로 돌려 놓습니다.
💡 rotate()
rotate()
메서드는 Collection
클래스의 deque
와 함께 쓸 수 있습니다.
파이썬에서 deque를 쓰는 이유는 list보다 빠르기 때문입니다.
list의 시간복잡도는 인 반면, deque는 입니다.
따라서 append/remove/push/pop연산이 많이 일어나는 알고리즘에서 deque가 활약할 수 있습니다.
deque에는 rotate()
라는 메서드가 있습니다. rotate는 말그대로 순환시켜주는 기능을 갖고있습니다.
예제 코드
from collections import deque
stack = deque([1, 2, 3, 4, 5])
stack.rotate(1) #[5, 1, 2, 3, 4]
stack.rotate(1) #[4, 5, 1, 2, 3]
stack.rotate(-1) #[5, 1, 2, 3, 4]
stack.rotate(-3) #[3, 4, 5, 1, 2]
Author And Source
이 문제에 관하여([1406] 에디터 | 백준 실버 2), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@yoongyum/1406-에디터-백준-실버-2저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)