나도 공부한다/알고리즘
[백준] 1238. 단축키 지정 (C++)
꾸빵이
2024. 3. 10. 15:28
Key
- 문자열 문제
- 개행 단위로 입력받는 방법을 알아야한다.
- 대문자와 소문자를 구별하지 않는다.
- 배열에 접근하는 방법, 배열에 새로운 값 삽입 방법을 알아야한다.
Idea
문제의 조건을 따라하면 되는 단순한 문제다.
하지만 개행 단위로 입력받기, uppercase, lowcase로 대소문자 변환하기, 배열 중간에 값 삽입하기를 모른다면 풀지 못하는 문제이다. 문자열 문제를 자주 풀지 않아서 이 세가지를 어떻게 처리할지 바로 기억하지 못하여 시간이 오래 걸렸다.
C++에서 개행 단위로 입력받기
cin 대신 getline(입력 스트림, 문자열) 으로 입력받는다. "\n"이 들어오면 입력이 끝난다.
주의할 점은, 이전에 cin으로 다른 값을 입력받았을 경우 그 때 입력했던 "\n"이 아직도 남아있어 getline이 동작하지 않을 수 있다. 따라서 모든 값을 getline으로 입력 받거나, cin.ignore() 함수를 사용하여 이전 버퍼를 지워줘야한다.
C++에서 모든 문자를 대문자로 변환하기
일반적으로 transform(str.begin(), str.end(), str.begin(), ::toupper);
이렇게 transfrom을 사용한다. 첫번째 인자~두번째 인자는 함수가 적용될 범위이고, 세번째 인자는 결과를 저장할 범위. 첫번째 인자와 동일할 경우 기존 값을 덮어쓰게 된다. 네번째 인자는 적용할 함수이다.
하지만 자주 사용되는 함수가 아니라 조금만 안써도 잊어버리게 되더라. 그래서 나는 toupper을 이용하여 문자에 직접 접근해서 하나씩 바꿔주는 방법을 선택했다.
C++에서 공백 단위로 끊기
stringstream을 사용한다. stringstream에 입력된 문자열을 공백 또는 개행 단위로 읽는 함수이다. 공백 또는 개행 단위로 잘린 단어는 word에 할당된다.
로직은 이렇다. 정말 문제 조건을 그대로 따라하기만 하면 된다.
1. 한 줄을 단어별로 나누어 각 단어의 첫글자가 사용중인지 검사
2. 만약 모든 단어의 첫글자가 사용중이라면 왼쪽부터 순회하여 사용중이지 않은 알파벳 찾기
2번 과정에서 주의해야할 점은, 단어 사이사이에 공백이 있으므로 지금 가리키고 있는 문자가 알파벳이 맞는지 확인해야한다.
Code
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
using namespace std;
int main() {
int N;
cin >> N;
bool check[26] = { false, };
vector<string> options(N);
vector<string> copyOptions(N);
cin.ignore();
for (int i = 0; i < N; i++) {
string str;
getline(cin, str);
options[i] = str;
for (char& c : str) {
c = toupper(c);
}
copyOptions[i] = str;
}
for (int i = 0; i < N; i++) {
stringstream ss(copyOptions[i]);
string word;
bool assigned = false;
// 단어별 처리
while (ss >> word) {
int idx = word[0] - 'A';
// 단어의 첫글자가 false면
if (!check[idx]) {
check[idx] = true;
assigned = true;
// 단축키로 지정
options[i].insert(copyOptions[i].find(word), "[");
options[i].insert(copyOptions[i].find(word)+2, "]");
break;
}
}
if (!assigned) {
for (int j = 1; j < copyOptions[i].length(); j++) {
// false이고 공백이 아닐때
if ((!check[copyOptions[i][j] - 'A']) && (copyOptions[i][j] - 'A' >= 0)) {
// 단축키로 지정
check[copyOptions[i][j] - 'A'] = true;
options[i].insert(j, "[");
options[i].insert(j + 2, "]");
break;
}
}
}
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < options[i].length(); j++) {
cout << options[i][j];
}
cout << "\n";
}
return 0;
}