일상
[c++] 백준 2914: 크로아티아 알파벳 본문
푸는데 시간이 꽤 걸린 예제라서 관련 포스팅을 진행하려고 한다. 처음 제출 코드는 아래와 같다
#include <iostream>
/*
c=
c-
dz=
d-
lj
nj
s=
z=
c : 99
= : 61
- : 45
d : 100
z : 122
l : 108
j : 106
n : 110
s : 115
z : 122
앞에 나오는 알파벳
c : -, = case 1
d : z, -, z= case 2
z : = case 3
l : j case 4
n : j case 5
s : = case 6
*/
int main() {
std::string s;
std::cin >> s;
int i = 0;
int count = 0;
while (i < s.length() - 1) {
if (int(s[i]) == 99) { //case1 : c
if (int(s[i + 1]) == 61) { // c=
i += 2;
++count;
}
else if (s[i + 1] == 45) { // c-
i += 2;
++count;
}
else {// c
++i;
++count;
}
}
else if (int(s[i] == 100)) { //case2 : d
if (int(s[i + 1]) == 122 && int(s[i + 2]) == 61) { //dz=
i += 3;
++count;
}
else if (s[i + 1] == 45) { // d-
i += 2;
++count;
}
else {
++i;
++count;
}
}
else if (int(s[i] == 122)) { //case3
if (int(s[i + 1]) == 61) { // z=
i += 2;
++count;
}
else {// z
++i;
++count;
}
}
else if (int(s[i] == 108)) { //case 4
if (int(s[i + 1]) == 106) { // lj
i += 2;
++count;
}
else {// l
++i;
++count;
}
}
else if (int(s[i] == 110)) { //case 5
if (int(s[i + 1]) == 106) { // nj
i += 2;
++count;
}
else {// l
++i;
++count;
}
}
else if (int(s[i] == 115)) { //case6
if (int(s[i + 1]) == 61) { // s=
i += 2;
++count;
}
else {// l
++count;
++i;
}
}
else {
++i;
++count;
}
}
if (i == s.length() - 1) { // 반복문의 마지막 비교 문자가 그냥 알파벳일 경우
count++;
}
std::cout << count << "\n";
}
소스의 의도를 설명하면 반복문을 통하여 문자열의 개별 문자에 대해 조건에 대한 검사를 진행한다. 이때 변수 i는 해당 문자의 index를 나타낸다. 만약 그 문자를 시작으로 크로아티아 알파벳이 나열된다면 굳이 바로 다음 문자에 대해 검사를 할 필요가 없으므로 변수 i를 해당 크로아티아 알파벳의 길이만큼 더해준다.
반복문을 빠져나오는 조건으로는 i < s.length() -1 로 해주었는데 최대 크로아티아 알파벳의 길이는 3이고 마지막-1 번째 문자열에서 길이 3의 문자에 대해 검사를 진행할 수 있기 때문이다(문자열의 마지막 문자는 null 이므로). 루프를 빠져나온 이후 한번 더 검사를 진행하는데 만약 i가 s.length() -1일 경우에는 마지막 검사 문자가 크로아티아 알파벳을 이루는 문자가 아니므로 문자열의 마지막 문자(null 제외)가 그냥 알파벳이기 때문에 알파벳의 개수에 1을 더해주면 된다.
사실 코드도 그렇고 설명도 그렇고 그리 직관적이지 못한 것 같아서 다른 분들은 어떻게 제출했나 블로그를 둘러보던 중 string의 find와 replace를 사용하여 문제를 해결하는 포스팅을 보았고 참고하여 다시 제출하였다.
관련 티스토리 : [C++ 백준] 2941 크로아티아 알파벳 (tistory.com)
#include <iostream>
#include <string>
int main() {
std::string s;
std::cin >> s;
std::string arr[8] = { "c=", "c-", "dz=", "d-", "lj", "nj", "s=", "z=" };
for (int i = 0; i < 8; i++) {
while (true) {
if (s.find(arr[i]) != std::string::npos) {
int index = s.find(arr[i]);
s.replace(index, arr[i].length(), "a");
}
else
break;
}
}
std::cout << s.length() << "\n";
}
지금 코드가 이전 코드보다는 훨씬 직관적인 것을 볼 수 있다. 반복문 안에서 while문을 쓰는 이유는 중복된 크로아티아 알파벳이 있을 수 있기 때문이다. STL 사용을 최대한 자제하려고 생각했는데 생각을 조금 바꿔서 STL을 활용한 예와 활용하지 않은 예를 모두 구현해본다면 도움이 꽤 될거라고 생각이 되었다.
'programming' 카테고리의 다른 글
[C++] 백준 2563 : 색종이 (0) | 2023.06.21 |
---|---|
[C++] 백준 10798: 세로 읽기 (0) | 2023.06.20 |
[c++] 백준 1316: 그룹 단어 체커 (0) | 2023.06.06 |
[c++] 백준 2444 (0) | 2023.05.31 |
[c++] 백준 1157 (0) | 2023.05.30 |