반응형

문제 출처 :


https://www.acmicpc.net/problem/5446



알고리즘 분석 :


문제 해결에 필요한 사항

1. 트라이


트라이를 쓸 줄 알면 풀 수 있는 문제이다.


우선 첫번째로 들어오는 지워야할 파일을 모두 트라이에 담아준다.


그 후 두번째로 지우면 안되는 파일을 트라이에 보내면서 지나가는 단어마다 isForbidden = true로 설정해준다.


(이때 지워야할 파일명이 이미 트라이에 있는데 지우지 말아야할 파일명이 트라이 안에 없다면 break를 해준다.


예를들어 filenames은 지워야할 파일인데 files로 시작하 파일은 지우면 안되는 파일이지만 트라이에 없으므로 


file까지만 isForbidden = true을 해주고 break를 해주면 된다.)



이제 트라이를 모두 구성했으니 queue에 트라이 현재 위치 포인터를 담아 트라이를 조사해보자.

isForbidden = true이면 다음 단어를 queue에 넣으며 넘어가야 한다.

이때 단어의 끝까지 조사가 됐다면 그 단어는 지워야 한다.(forbidden이어도 지워야할 단어이므로)
즉, ans++

만약 현재 위치가 isForbidden = false이면 이 단어뒤로부터는 *을 통해 모두 지울 수 있으므로
ans++만하고 queue에는 집어넣지 않는다.

이때 예외는 m == 0이라면 *로 모든 파일을 지우면 되니 답은 1이다.



소스 코드 : 


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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include <iostream>
#include <cstdio>
#include <queue>
 
using namespace std;
 
const int MAX_NODE = 63;
 
int convert(char ch)
{
    if ('a' <= ch && ch <= 'z')
        return (ch - 'a');
    else if ('A' <= ch && ch <= 'Z')
        return (37 + ch - 'A');
 
    else if (ch == '.')
        return 26;
 
    else if ('0' <= ch && ch <= '9')
        return (ch - '0' + 27);
}
 
char recover(int n)
{
    if (<= n && n <= 25)
        return ('a' + n);
    else if (n == 26)
        return '.';
    else if (27 <= n && n <= 36)
        return (n - 27 + '0');
    else if (37 <= n && n <= 63 - 1)
        return (n - 37 + 'A');
}
 
 
struct Trie {
    Trie *next[MAX_NODE];
    bool isEnd, isForbidden, hasChild;
    Trie() {
        for (int i = 0; i < MAX_NODE; i++)
        {
            next[i] = nullptr;
            isEnd = isForbidden = false;
        }
    }
 
    ~Trie() {
        for (int i = 0; i < MAX_NODE; i++)
            if (next[i])
                delete next[i];
    }
};
 
Trie *root;
 
int main()
{
    int tc;
    scanf("%d"&tc);
 
    while (tc--)
    {
        root = new Trie;
 
        int n;
        scanf("%d"&n);
 
        for (int i = 0; i < n; i++)
        {
            char str[25];
            scanf("%s", str);
 
            Trie *pos = root;
            for (int j = 0; str[j]; j++)
            {
                int nowCh = convert(str[j]);
 
                if (!pos->next[nowCh])
                    pos->next[nowCh] = new Trie;
 
                pos = pos->next[nowCh];
            }
 
            pos->isEnd = true;
        }
 
        int m;
        scanf("%d"&m);
 
        if (!m)
        {
            printf("1\n");
            continue;
        }
        for (int i = 0; i < m; i++)
        {
            char str[25];
            scanf("%s", str);
 
            Trie *pos = root;
 
            for (int j = 0; str[j]; j++)
            {
                int nowCh = convert(str[j]);
 
                if (pos->next[nowCh])
                    pos->next[nowCh]->isForbidden = true;
                else
                    break;
 
                pos = pos->next[nowCh];
            }
        }
 
        int ans = 0;
        queue<Trie *> q;
 
        q.push(root);
 
        while (!q.empty())
        {
            Trie *cur = q.front();
 
            q.pop();
            for (int i = 0; i < MAX_NODE; i++)
            {
                if (cur->next[i])
                {
                    if (cur->next[i]->isForbidden)
                    {
                        if (cur->next[i]->isEnd)
                            ans++;
 
                        q.push(cur->next[i]);
                    }
                    else
                        ans++;
                }
            }
        }
 
        printf("%d\n", ans);
    }
 
    return 0;
}
 
//                                                       This source code Copyright belongs to Crocus
//                                                        If you want to see more? click here >>
Crocus



반응형

'Applied > 알고리즘 문제풀이' 카테고리의 다른 글

[CSAcademy] Prefix Free Subset  (4) 2018.03.11
[9202번] Boggle  (0) 2018.03.10
[1744번] 수 묶기  (0) 2018.03.08
[13717번] 포켓몬 GO  (0) 2018.03.07
[10545번] 뚜기뚜기메뚜기  (0) 2018.03.06