본문 바로가기
Develop/백준 (Cpp)

[백준] 5052번 : 전화번호 목록 (C++)

by Tarra 2023. 8. 17.

5052번 : 전화번호 목록


문제)

전화번호 목록이 주어진다. 이때, 이 목록이 일관성이 있는지 없는지를 구하는 프로그램을 작성하시오.

전화번호 목록이 일관성을 유지하려면, 한 번호가 다른 번호의 접두어인 경우가 없어야 한다.

예를 들어, 전화번호 목록이 아래와 같은 경우를 생각해보자

  • 긴급전화: 911
  • 상근: 97 625 999
  • 선영: 91 12 54 26

이 경우에 선영이에게 전화를 걸 수 있는 방법이 없다. 전화기를 들고 선영이 번호의 처음 세 자리를 누르는 순간 바로 긴급전화가 걸리기 때문이다. 따라서, 이 목록은 일관성이 없는 목록이다.

 

 

 

입력 :

첫째 줄에 테스트 케이스의 개수 t가 주어진다. (1 ≤ t ≤ 50) 각 테스트 케이스의 첫째 줄에는 전화번호의 수 n이 주어진다. (1 ≤ n ≤ 10000) 다음 n개의 줄에는 목록에 포함되어 있는 전화번호가 하나씩 주어진다. 전화번호의 길이는 길어야 10자리이며, 목록에 있는 두 전화번호가 같은 경우는 없다.

 

 

 

출력 :

각 테스트 케이스에 대해서, 일관성 있는 목록인 경우에는 YES, 아닌 경우에는 NO를 출력한다.

 

 

 

 

 

 

풀이)

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
 
using namespace std;
 
// Trie 자료구조를 사용하기 위한 struct
struct Trie
{
public:
    // 해당 글자에서 끝났는지 판별하기 위한 boolean
    bool finish;
    // 다음 글자로 넘어가기 위한 Trie 배열
    Trie* next[10];
 
public:
    // 전화번호를 삽입하는 함수이다.
    void insert(const char* key)
    {
        // 전화번호의 마지막이라면
        // 해당 노드에 finish를 1로 바꿔놓는다.
        if (*key == '\0')
        {
            this->finish = 1;
            return;
        }
        else
        {
            // 해당 노드의 인덱스를 구하고
            int cur = *key - '0';
            // 다음 노드에 값이 들어있지 않다면
            // Trie를 동적할당하여 넣어준다.
            if (next[cur] == nullptr)
            {
                next[cur] = new Trie();
            }
            // 해당 노드에서 다음 글자의 insert를 진행한다.
            next[cur]->insert(key + 1);
        }
    }
 
    bool find(const char* key)
    {
        // 전화번호가 모두 끝날 때까지 겹치는 것이 없다면
        if (*key == '\0'return true;
    
        // 전화번호는 짧은 것부터 insert되므로 중간에 finish가 나온다면
        // 해당 번호는 일관성이 없게 된다.
        if (this->finish) return false;
 
        int cur = *key - '0';
        // 다음 글자에 대한 배열이 없다면 새롭게 추가할 수 있음
        if (next[cur] == nullptr) return true;
        return next[cur]->find(key + 1);
    }
 
 
public:
    Trie()
        :finish(0)
    {
        fill(next, next + 10, nullptr);
    }
 
    ~Trie()
    {
        for (int i = 0; i < 10; i++)
        {
            if (next[i])
            {
                delete next[i];
            }
        }
    }
};
 
int t, n;
 
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
 
    cin >> t;
 
    for (int _ = 0; _ < t; _++)
    {
        cin >> n;
        Trie t;
 
        // 각 테스트 케이스에 마다 새롭게 초기화한다.
        string temp;
        vector<string> vec;
 
        bool flag = 0;
        // 짧은 전화번호부터 들어가야 하기 때문에
        // 일단 vector에 저장한 후 
        // 정렬하여 오름차순으로 만든다.
        for (int i = 0; i < n; i++)
        {
            cin >> temp;
            vec.push_back(temp);
        }
 
        sort(vec.begin(), vec.end());
 
        for (int i = 0; i < n; i++)
        {    // 가장 짧은 전화번호는 아무런 연관성이 없으므로 
            // 바로 넣는다.
            if (i == 0) t.insert(vec[i].c_str());
            else
            {    // 넣기 전에 일관성 체크를 진행한다.
                if (!t.find(vec[i].c_str()))
                {
                    flag = 1;
                }
                else
                {
                    t.insert(vec[i].c_str());
                }
            }
        }
 
        if (!flag) cout << "YES\n";
        else cout << "NO\n";
    }
 
    return 0;
}
cs

 

트라이 자료구조에 대한 이해가 많이 필요했던 문제였다.

해당 자료구조에 대한 구현은 다음의 블로그를 참고하였다.

https://eun-jeong.tistory.com/29

 

[자료구조] 트라이 (Trie) C++ 구현

트라이 (Trie) 우리가 여러 개의 문자열을 가지고 있을 때, 어떤 문자열이 그 문자열 중 하나인지 알아내는 방법을 생각해보자. 단순하게 일일히 비교하는 방법이 있겠지만, 이러한 방법은 매우

eun-jeong.tistory.com

 

 


출처 : https://www.acmicpc.net/problem/5052 

 

5052번: 전화번호 목록

첫째 줄에 테스트 케이스의 개수 t가 주어진다. (1 ≤ t ≤ 50) 각 테스트 케이스의 첫째 줄에는 전화번호의 수 n이 주어진다. (1 ≤ n ≤ 10000) 다음 n개의 줄에는 목록에 포함되어 있는 전화번호가

www.acmicpc.net