Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
🔗 문제 링크
BOJ 1599 - 민식어
✔️ 소요된 시간
30m
✨ 수도 코드
1. 문제 설명
알파벳의 문자 체계를 변형한 "민식어" 라는 문자 체계가 있습니다.
"민식어"의 글자 순서는 a b k d e g h i l m n ng o p r s t u w y 순으로 구성되어 있습니다.
이중에서 ng 는 n과 o 사이의 완전히 새로운 문자입니다.
이 문제는 "민식어"로 구성된 단어를 입력 받아 사전 순으로 출력하는 문제입니다.
2. 문제 해석 및 풀이
1. 정렬 방식
보자마자 정렬을 이용하는 문제라는 것은 다들 아시겠죠?
우리가 일반적인 알파벳 문자 체계의 단어를 정렬해서 출력한다면
C++
에서는 다음과 같이 쉽게 코드를 짤 수 있습니다.하지만 이 문제는 알파벳 문자 체계를 약간 변형한 민식어 문자 체계를 따르는 단어를 정렬해야 하기 때문에 정렬을 할 때 정렬 방식을 정해주어야 합니다.
정렬 방식은 두 가지가 있습니다.
저는 1번 방식을 택했습니다.
이를 위해서는 민식어 단어를 알파벳 단어로 번역하는
translation
함수를 만들어야 합니다.이제 이 반복문을 토대로 한글자씩 문자를 바꾸어 알파벳 단어로 바꾸어 봅시다.
2. 민식어 단어를 알파벳 단어로 번형 (1)
"민식어"의 글자 순서는 알파벳의 순서를 약간 변형해서 따르고 있기에 우선 이를 나열해서 비교해봅시다.
알파벳과 민식어의 차이는 다음을 제외하면 존재하지 않습니다.
1번은 전혀 문제가 될 것이 없습니다.
알파벳 몇 글자가 존재하지 않더라도 민식어의 글자 순서는 'k'와 'ng'를 제외하면 전부 알파벳의 순서를 따르기 때문입니다.
따라서 민식어의 'k'와 'ng'를 제외한 모든 문자들은 알파벳으로 번역 시 문자를 바꾸지 않아도 상관이 없습니다.
2번은 단순하게 민식어에서 'k'를 'c'로 바꾸면 됩니다.
'k'를 'c'로 바꾸면 알파벳의 순서를 따르기 때문에 알파벳의 정렬 기준에 맞춰집니다.
(민식어에는 'c'라는 문자가 존재하지 않으므로 민식어의 'k'를 'c'로 바꾸어도 무방합니다.)
3. 민식어 단어를 알파벳 단어로 번형 (2)
문제는 3번입니다. 3번이 문제가 되는 이유는 크게 두 가지 있습니다.
이를 염두 해두면서 해결 방법을 찾아봅시다.
우선 'ng'라는 글자로 구성된 단어의 입력을 받아야 합니다.
민식어 단어에 구성된 글자를 하나씩 비교하므로
i번째 글자에 'n'이 나오면 그 뒤에 'g'가 나오는지 조건문을 통해서 구별하면 될 것입니다.
그 후엔 이 'ng'라는 글자를 이 위치에 오는 알파벳으로 바꾸어 주면 될 것 처럼 보입니다.
하지만 'ng'는 알파벳에서는 존재하지 않는 'n'과 'o' 사이에 오는 글자이기 때문에 그럴 수 없습니다.
그렇다면 민식어 글자에서 'ng' 이후에 오는 글자들을 알파벳 문자로 변형할 때 한 글자씩 옮겨주도록 합시다.
민식어 문자 체계에서 맨 끝 글자는 'y'이기 때문에 한 글자씩 옮겨주어도 알파벳의 마지막 글자인 'z'를 넘지 않으므로 가능한 방법입니다.
'ng' 뒤에 있는 'o' ~ 'y'까지 한 글자씩 옮겨주면 'ng'의 자리에 'o'가 들어올 수 있는 것을 확인할 수 있습니다.
이는 'n'보다 큰 문자에 증가연산
++
를 해주는 것으로 해결할 수 있습니다.이제 민식어 단어에서 'ng'가 나온다면 'o'로 변경해주면 되겠지요.
'ng'는 알파벳 두 글자로 되어 있으므로 우선
i
번째 글자를 지워주고,i+1
번째 글자로 이동해봅시다.그 후
i+1
번째 글자를o
로 변형해주면 될 것입니다.이렇게 되면 참 좋겠지만 아직 문제가 남아있습니다.
왜냐하면 'ng'를 'o'로 바꾸게 되면 알파벳 단어는 민식어 단어보다 사이즈가 줄어듭니다.
'ng'는 알파벳 두 글자로 구성되어 있기 때문이죠.
따라서 위 코드는 우리가 원하는 대로 작동하지 않고 다음과 같이 작동합니다.
이를 해결하기 위해서
s_diff
라는 변수로alpha_str
의 인덱스 차이를 조절해주어야 합니다.s_diff
를 처음에0
으로 초기화 해주고, 'ng'라는 글자가 나왔을 때 차이가1
만큼 벌어지므로++s_diff
해주면 될 것 입니다.또한 'ng'가 한번 나오면 이를 'o'라는 글자로 수정하고 나면 크기 차이가 계속 진행되므로
함수 내에 있는
alpha_str[i]
를 일괄적으로alpha_str[i-s_diff]
로 변경해줍니다.따라서 함수의 최종 코드는 다음과 같습니다.
std::string translation(std::string min_str)
{
int s_diff = 0; // alpha_str과 min_str의 크기 차이
std::string alpha_str = min_str;
for (int i = 0; i < min_str.size(); i++) {
if (min_str[i] == 'k') alpha_str[i-s_diff] = 'c';
else if (min_str[i] > 'n') alpha_str[i-s_diff]++;
else if (min_str[i] == 'n' && i+1 < min_str.size() && min_str[i+1] == 'g') {
alpha_str.erase(alpha_str.begin() + (i++) - s_diff);
alpha_str[i - (++s_diff)] = 'o';
}
}
return alpha_str;
}
3. 최종 코드
string
클래스를 활용하면 부등호를 활용하여 문자열의 사전순 비교가 가능합니다.📚 새롭게 알게된 내용
PR이 늦어졌네요. 죄송합니다..
오늘은 조금 단순한 문제를 들고 왔습니다.
원래 연결리스트를 공부해서 관련 문제를 풀어보려고 했는데
뭔가 지난번 문제들 성격이랑 너무 비슷해서 아예 다른 문제를 선택해서 왔네요.
다음 PR은 순환 알고리즘을 공부하여 풀어오겠습니다!