solved.ac : Silver V
https://www.acmicpc.net/problem/1316
그룹 단어는 단어에 문자가 연속해서 나타나는 경우를 말한다. 한번 나왔던 문자는 연속해서 나올 수 있지만 다른 문자 뒤에 또 나타나면 그건은 그룹 문자가 아니다. 예를 들어 aaabbbccc는 같은 문자가 연속해서 나왔지만 a, b, c 차례로 있으므로 그룹 문자이다. 또한 bbbcccaaa도 순서는 거꾸로지만 연속으로 된 문자 외에 겹치는 문자가 없으므로 그룹 문자이다. 반면에 aabbccaa는 떨어져있는 a가 2개 있으므로 그룹 문자가 아니다.
이제 그룹 문자를 이해했으면 이를 활용하여 다음과 같은 로직을 짤 수 있다.
한번 나왔던 문자를 메모하기 위해 marker
라는 bool 형태의 배열을 만든다. 배열의 길이는 알파벳의 갯수인 26개로 초기화한다. 그럼 marker
배열의 요소들은 전부 false로 초기화된다. 문자가 나왔을 때 marker
의 해당 위치의 bool 값을 확인하여 이전에 같은 문자가 나왔는지 확인을 할 수 있다.
현재 문자 이전에 어떤 문자가 나왔는지 확인을 하기 위해 previous
라는 char형 변수를 선언하고 \0
으로 초기화한다.
반복문으로 단어의 각 문자를 확인한다.
문제에서는 알파벳 소문자만 나온다고 명시했으므로 문자의 ascii값 - 97로 marker
의 요소번호와 대응될 수 있도록 한다. (참고로 'a'의 ascii값은 97이다.)
문자가 연속해서 나오는 경우를 확인해야 하므로 previous != ch
조건으로 이전에 나온 문자와 비교하고 틀리다면 marker
의 요소 값이 true면 그룹 문자가 아니므로 false를 반환한다.
만약 이전의 조건문을 실행하지 않았다면 previous
와 현재 문자의 값이 틀릴 경우에만 previous
의 값을 현재 문자로 바꾸고 marker
의 요소 값을 true로 바꾼다.
만약 모든 문자를 확인했다면 이 단어는 그룹 문자이므로 마지막으로 true를 반환한다.
using System;
internal static class Program
{
private static void Main()
{
int tc = int.Parse(Console.ReadLine());
int groupWordCount = 0;
for (int i = 0; i < tc; i++)
{
if (Console.ReadLine().IsGroupWord())
{
groupWordCount++;
}
}
Console.WriteLine(groupWordCount);
}
private static bool IsGroupWord(this string word)
{
bool[] marker = new bool[26];
char previous = '\0';
foreach (char ch in word)
{
int idx = ch - 97;
if (previous != ch && marker[idx])
{
return false;
}
if (previous != ch)
{
previous = ch;
marker[idx] = true;
}
}
return true;
}
}