코딩 테스트

[코딩테스트 32일차] BAEKJOON 2941번 : 크로아티아 알파벳

sunlight-dby 2025. 6. 20. 01:58

[BAEKJOON 2941번 : 크로아티아 알파벳]

[문제]


[고찰]

저는 이 문제를 alphabets이라는 7의 크기를 가지는 string 배열을 만들어, 글자 수가 2개인 크로아티아 알파벳을 값으로 지정하였고, aplhabet이라는 string 타입의 변수를 만들어 글자 수가 3개인 크로아티아 알파벳인 'dz='를 지정하였습니다.

 

그 후 i = 0부터 입력받은 단어인 word의 size만큼 반복하면서, 크로아티아 알파벳인지 아닌지를 판별하여 해당 문제를 풀었습니다.

 

먼저 i + 1이 word.size()보다 크거나 같다면, 마지막 글자라는 의미이기 때문에 바로 알파벳 수를 1 더해줬습니다.

 

만약 아니라면, string str 변수를 만들어, string(1, word[ i ])와 word[i + 1]을 더해주었고,이후 for (string ss : alphabets)의 반복문을 통해 str이 ss라면 알파벳 수를 1 더해주고 i 또한 1을 더 해주어, 크로아티아 알파벳은 넘기게 하였습니다.또한 isNext라는 boolean 변수를 true로 하여, 해당 반복문이 끝난 후 isNext가 false일 때를 고려하였습니다.

 

isNext가 false일 때, 혹여나 크로아티아 알파벳 'dz='일수도 있기 때문에, str에 word[i + 2]를 더해준 후,str이 aplhabet('dz=')인지와 'dz='이 마지막 글자인지를 확인하기 위해 i가 word.size() - 2보다 작은지를 체크하여주었습니다.

 

만약 맞다면, 알파벳 수를 1 더해주고, i는 2를 더해주어 크로아티아 알파벳은 넘기게 하였습니다.

만약 아니라면, 크로아티아 알파벳이 아닌 그냥 알파벳이기 때문에, 알파벳 수를 1 더해주었습니다.

 

 

제 방식은 좀 복잡하게 구현되었는데, 다른 분들의 풀이를 보니 find와 replace를 써서 간편하게 푼 것을 확인하였습니다.

그래서 find와 replace를 쓴 방식을 정리하고자 합니다.

 

아래는 제가 작성한 코드입니다.

#include <iostream>

using namespace std;

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);

	string word;
	cin >> word;

	string alphabets[7] = { "c=", "c-", "d-", "lj", "nj", "s=", "z=" };
	string alphabet = "dz=";
	int count = 0;
	bool isNext = false;

	for (int i = 0; i < word.size(); i++)
	{
		string str;

		if ((i + 1) >= word.size())
		{
			count++;
			break;
		}
		else
		{
			str = string(1, word[i]) + word[i + 1];
		}

		for (string ss : alphabets)
		{
			if (str == ss)
			{
				count++;
				i++;
				isNext = true;
				break;
			}
		}

		if (!isNext)
		{
			str += word[i + 2];
			if (str == alphabet && i < word.size() - 2)
			{
				count++;
				i += 2;
			}
			else
			{
				count++;
			}
		}

		isNext = false;
	}

	cout << count;

	return 0;
}

[개념]

일단 제가 푼 방식에서도 하나 짚고 넘어갈 것이 있습니다.

 

처음에는 string = char + char 형식으로 str을 만들려고 하다가, 아차 싶어서 위의 코드에서 보시다시피 string = string + char 형태로 바꾸었습니다.

 

까먹고 있었던 내용인데, char + char은 아스키코드로 계산이 되기 때문에, 원하는 방식으로 string이 만들어지지 않습니다.

 

따라서 아래와 같은 방식으로 string을 만들어야 합니다.

 

문자(character)의 결합

  • string 생성자 이용
string str(1, char1);
str1 += char2;
  • push_back() 함수 이용
string str;
str.push_back(char1);
str.push_back(char2);
  • char + char은 아스키코드로 계산됨

 

find() 함수

문자열에서 문자 및 문자열 탐색하기 위한 함수로, 다양한 형태의 오버로딩이 존재합니다.

만약 문자열을 찾는데 성공하였다면, 해당 문자열의 시작 위치를 반환하고, 찾지 못했따면 npos를 리턴합니다.

※ npos는 string::npos로 정의되는 상수로, -1의 값을 가집니다.

size_type find(const basic_string& str, size_type pos = 0) const;
  • 탐색은 'pos'부터 시작되며, 문자열에서 'str'의 위치를 리턴합니다.
size_type find(const CharT* s, size_type pos, size_type count) const;
  • 탐색은 'pos'부터 시작되며, 's'가 가리키는 문자부터 'count'개 만큼을 취한 부분 문자열을 원 문자열에서 찾습니다.
  • 참고로 's' 중간에 'NULL'이 있어도 됩니다.
size_type find(const CharT* s, size_type pos = 0) const;
  • 탐색은 'pos'부터 시작되며, 's'가 가리키는 문자열을 원 문자열에서 검색합니다. 이 때 's'는 널 종료 문자열로 간주됩니다.
size_type find(CharT ch, size_type pos = 0) const;
  • 탐색은 'pos'부터 시작되며, 원 문자열에서 문자 'ch'의 위치를 찾습니다.

 

 

replace() 함수

문자열의 일부를 다른 문자열로 치환하는 함수로, 다양한 형태의 오버로딩이 존재합니다.

basic_string& replace(size_type pos, size_type count, const basic_string& str);
basic_string& replace(const_iterator first, const_iterator last, const basic_string& str);
  • 기존 문자열의 'pos'부터 'count'개의 문자들을, 혹은 'first'부터 'last' 전까지의 문자들을 'str'로 치환합니다.
basic_string& replace(size_type pos, size_type count, 
    const basic_string& str, size_type pos2, size_type count2 = npos);
  • 기존 문자열의 'pos'부터 'count'개의 문자들을 'str'의 'pos2'부터 'count2'개의 문자들로 치환합니다.
template <class InputIt>
basic_string& replace(const_iterator first, const_iterator last, InputIt first2, InputIt last2);
  • 기존 문자열의 'first'부터 'last'를 'first2'부터 'last2'로 치환합니다.
basic_string& replace(size_type pos, size_type count, const CharT* cstr, size_type count2);
basic_string& replace(const_iterator first, const_iterator last, const CharT* cstr, size_type count2);
  • 기존 문자열의 'pos'부터 'count'개의 문자를, 혹은 'first'부터 'last'까지의 문자를 'cstr'이 가리키는 배열의 'count2'개만큼의 문자들로 치환합니다.
  • 이 때 'cstr'이 가리키는 문자 배열은 널 문자를 포함하고 있어도 됩니다.
basic_string& replace(size_type pos, size_type count, const CharT* cstr);
basic_string& replace(const_iterator first, const_iterator last, const CharT* cstr);
  • 기존 문자열의 'pos'부터 'count'개의 문자를, 혹은 'first'부터 'last'까지의 문자를 'cstr'이 가리키는 널 종료 문자열로 치환합니다.
basic_string& replace(size_type pos, size_type count, size_type count2, CharT ch);
basic_string& replace(const_iterator first, const_iterator last, size_type count2, CharT ch);
  • 기존 문자열의 'pos'부터 'count'개의 문자를, 혹은 'first'부터 'last'까지의 문자를 'ch' 문자 'count2'개로 치환합니다.
basic_string& replace(const_iterator first, const_iterator last, std::initializer_list<CharT> ilist);
  • 기존 문자열의 'first'부터 'last'까지의 문자들을 'ilist'에 있는 문자들로 바꿉니다.

[정리]

기존에 알고있던 함수들이더라도, 자주 활용하지 않으면 활용법을 떠올리지 못하는 것 같습니다.

문제 수를 많이 풀면 풀수록 이런 문제들은 더 나아질 것이라 생각하고, 더욱 많은 문제를 접하는 것에 목적을 둘 것입니다.


[Solution]

#include <iostream>
#include <string>

using namespace std;

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);

	string word;
	cin >> word;

	string alphabets[8] = { "c=", "c-", "dz=", "d-", "lj", "nj", "s=", "z=" };
	int idx;

	for (int i = 0; i < 8; i++)
	{
		while (1)
		{
			idx = word.find(alphabets[i]);

			if (idx == string::npos)
				break;
			word.replace(idx, alphabets[i].size(), "0");
		}
	}

	cout << word.size();

	return 0;
}