Algorithm/baekjoon
[BOJ 1406] 에디터
식빵민
2022. 7. 25. 18:39



1406번: 에디터
첫째 줄에는 초기에 편집기에 입력되어 있는 문자열이 주어진다. 이 문자열은 길이가 N이고, 영어 소문자로만 이루어져 있으며, 길이는 100,000을 넘지 않는다. 둘째 줄에는 입력할 명령어의 개수
www.acmicpc.net
문제 분석
- string으로 문제를 풀어보려 한다.
- 계획 :
커서 : index i
L : (i=0) 무시 (i≠0) i-=1
D : (i=length-1) 무시 (i≠length-1) i+=1;
B : (i≠0) str.erase(i-1);
(i=0) 무시
P $: str.insert(i,$)
string str;
int n,last,i;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin>>str;
cin>>n;
i = (int)str.length(); // index i 초기화
while(n--){
char cmd;
cin>>cmd;
if(cmd == 'L'){
if(i!=0){
i -=1;
}else continue;
}
else if(cmd == 'D'){
if(i!=str.length()){
i +=1;
}else continue;
}
else if(cmd == 'B'){
if(i!=0){
str.erase(i-1,1);
i -=1;
}else continue;
}
else{
string c;
cin>>c;
str.insert(i, c);
i+=1;
}
}
cout<<str<<"\n";
return 0;
}
시간제한이 0.3초라는 걸 염두하지 않은 코드 였다...
위 코드는 string, 즉 char형 배열을 기반으로 짜여진 코드이므로 삽입/삭제시에 상당한 시간이 소모된다.
고로 당연히 시간초과가 났다. 이에 삽입/삭제에 효율적인 <list>를 이용해 보고자 했다.
계획:
string의 각 char을 list에 추가
커서의 역할을 index i 대신 iterator iter로
나머지 논리는 string기반 코드와 같다.
#include <iostream>
#include <list>
using namespace std;
list<char> str;
string in;
int n;
list<char>::iterator iter;
int main() {
cin >> in;
cin >> n;
for (int i = 0; i < in.length(); i++) {
str.push_back(in[i]);
}
iter = str.end();
while (n--) {
char cmd;
cin >> cmd;
if (cmd == 'L') {
if (iter != str.begin())
iter--;
} else if (cmd == 'D') {
if (iter != str.end())
iter++;
} else if (cmd == 'B') {
if (iter != str.begin()) {
iter--;
iter = str.erase(iter);
}
} else if (cmd == 'P') {
char c;
cin >> c;
str.insert(iter, c);
}
}
for (iter = str.begin(); iter != str.end(); iter++)
cout << *iter;
return 0;
}
느낀점
- 이 코드를 짤때, 중간과정을 검정한답시고 iter가 처음 부터 끝까지 살펴보는 코드를 while문 안에 넣었다.
문제는 <list>를 살펴보는 iterator를 iter로 사용해서 계속 iter가 마지막 원소(ending 노드 직전 노드)로 초기화 되어 iter가 제대로 이동하지않았다는 점이다.
이 문제를 생각하는데 꽤 오랜시간이 걸렸고,(사실 친구가 코드보고는 알려줬다...) 이에 스스로 자책하게 됐다. - 나머지 로직은 처음 생각한대로 옳은 로직이었다.
시간 복잡도
- 삽입/삭제 연산 → O(1)
- while문 n번 반복 → O(n)
➣ O(n)