문제 설명
문자열 S가 주어졌다고 가정해 봅시다. 아말(Amal)과 비말(Bimal)은 다음과 같은 규칙의 게임을 하고 있습니다. 먼저 플레이하는 사람, 즉 아말은 탐정 역할을 맡아 '사건'을 조사하고 원인을 밝혀내야 합니다. 아말은 답이 "예(Yes)" 또는 "아니오(No)"로 나뉘는 질문을 자유롭게 던질 수 있습니다. 이때 질문의 마지막 글자가 모음이라면 상대방은 "예"라고 답하고, 그렇지 않다면 "아니오"라고 답합니다. 여기서 모음은 A, E, I, O, U, Y 여섯 개입니다. 우리에게 질문 문자열 S가 주어지며, 이에 대한 답을 구하는 것이 목표입니다.
예를 들어 입력이 S = "Is it in university?"라면 출력은 Yes가 됩니다. 물음표 바로 앞의 마지막 알파벳이 'y'이고, y는 모음으로 간주되기 때문입니다.
해결 접근 방법
이 문제는 다음 단계를 통해 해결할 수 있습니다.
- 모음 집합을 "AEIOUYaeiouy"로 정의합니다. 대소문자를 모두 포함해야 합니다.
- 문자열 S를 처음부터 끝까지 순회하면서 마지막으로 등장하는 알파벳 문자를 찾습니다.
- 찾은 문자가 모음 집합에 포함되어 있으면 "YES"를 반환하고, 그렇지 않으면 "NO"를 반환합니다.
위 로직을 의사 코드로 표현하면 다음과 같습니다.
s := "AEIOUYaeiouy"
for initialize i := 0, when i < size of S, update (increase i by 1), do:
t := S[i]
if t is alphabetic, then:
ans := t
if ans is in s, then:
return "YES"
Otherwise
return "NO"여기서 핵심은 순회 과정에서 조건을 만족할 때마다 ans 값을 갱신하기 때문에, 반복문이 끝나면 자연스럽게 마지막 알파벳이 남는다는 점입니다. 또한 isalpha() 함수를 사용해 알파벳이 아닌 문자(공백, 물음표 등)는 무시합니다.
C++ 구현 예시
보다 나은 이해를 위해 실제 구현 예시를 살펴보겠습니다.
#include <bits/stdc++.h>
using namespace std;
string solve(string S){
string s = "AEIOUYaeiouy";
char ans;
for (int i = 0; i < S.size(); i++){
char t = S[i];
if (isalpha(t))
ans = t;
}
if (s.find(ans) != -1)
return "YES";
else
return "NO";
}
int main(){
string S = "Is it in university?";
cout << solve(S) << endl;
}입력
"Is it in university?"
출력
YES
마무리
이 알고리즘의 시간 복잡도는 문자열의 길이를 N이라 할 때 O(N)이며, find 함수 호출은 최대 12개의 모음 문자만 검사하므로 사실상 상수 시간에 처리됩니다. 문자열을 한 번만 순회하면 되므로 매우 효율적이며, 대소문자 구분 없이 모음을 판별해야 하는 다양한 응용 문제에도 쉽게 확장할 수 있습니다.