Skip to content

염라대왕은 이승의 사람들의 모든 이름을 가지고 있다.

어느날 저승에 일어난 진도 8.0 지진에 항상 정리되어 있던 이승 명부가 흐트러졌다.

이승 명부는 이름의 길이가 짧을수록 이 앞에 있었고, 같은 길이면 사전 순으로 앞에 있었다.

이왕 이렇게 된 김에 모든 이름을 다시 정리하고 같은 이름은 하나만 남겨놓기로 한 염라대왕을 도와주자.

[입력]

첫 번째 줄에 테스트 케이스의 수 T(1 ≤ T ≤ 50)가 주어진다.

각 테스트 케이스의 첫 번째 줄에는 이승 명부의 이름 개수 N(1 ≤ N ≤ 20,000)이 주어진다.

각 테스트 케이스의 두 번째 줄부터 N개의 줄에 걸쳐서 알파벳 소문자로 이루어진 이름들이 주어진다.

이름에는 공백이 포함되지 않으며 최소 1개, 최대 50개의 알파벳으로 이루어져 있다.

[출력]

각 테스트 케이스마다 ‘#x’(x는 테스트케이스 번호를 의미하며 1부터 시작한다)를 출력하고,

정리된 이름을 한 줄에 하나씩 출력하라. 같은 이름은 한 번만 출력해야 하는 것을 주의하라.

풀이#

단순한 정렬문제이다. 나는 Quick Sort 를 배운 참에 써먹어 보기로 결심했다. 정렬코드는 사실 그대로고, 메인함수에서 정렬방식에 대한 방법을 지정해주는 것으로 문제의 요구사항을 충족시킬 수 있었다.

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

  freopen("s_input.txt", "r", stdin);

  size_t t;
  cin >> t;
  for (size_t tc = 1; tc <= t; ++tc) {
    cout << "#" << tc << "\\n";

    size_t n;
    cin >> n;
    vector<string> ls;

    for (size_t i = 0; i < n; ++i) {
      string word;
      cin >> word;
      ls.push_back(word);
    }

    sol1::sort(ls.begin(), ls.end(), [](auto a, auto b) {
      if (a.size() == b.size()) {
        // sort by string
        return a < b;
      }
      // sort by length
      return a.size() < b.size();
    });

    // make it unique
    auto end = std::unique(ls.begin(), ls.end());
    std::for_each(ls.begin(), end, [](auto elem) { cout << elem << "\\n"; });
  }

  return 0;
}

문자열의 길이를 우선적으로 정렬하고, 길이가 같으면 일반적인 사전순(Lexicographic order)으로 정렬한다. 위와 같이 정렬의 방식을 알고리즘 밖에서 정의하는 패턴을 전략패턴 Template Method Pattern / Strategy Pattern 이라고 부른다.

마지막으로 같은 단어를 제거하기 위해 std::unique 함수를 사용했다. 얘는 중복되는 원소를 제거하여 줄어든 컨테이너의 마지막 위치를 가리켜준다.