1/*
2 * ํธ๋ผ์ด (Trie)
3 * Prefix Tree, Autocomplete, XOR Trie
4 *
5 * ๋ฌธ์์ด ๊ฒ์์ ์ํ ํธ๋ฆฌ ์๋ฃ๊ตฌ์กฐ์
๋๋ค.
6 */
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <stdbool.h>
12
13#define ALPHABET_SIZE 26
14
15/* =============================================================================
16 * 1. ๊ธฐ๋ณธ ํธ๋ผ์ด
17 * ============================================================================= */
18
19typedef struct TrieNode {
20 struct TrieNode* children[ALPHABET_SIZE];
21 bool is_end;
22 int count; /* ์ด ์ ๋์ฌ๋ก ์์ํ๋ ๋จ์ด ์ */
23} TrieNode;
24
25TrieNode* trie_create_node(void) {
26 TrieNode* node = malloc(sizeof(TrieNode));
27 node->is_end = false;
28 node->count = 0;
29 for (int i = 0; i < ALPHABET_SIZE; i++)
30 node->children[i] = NULL;
31 return node;
32}
33
34void trie_free(TrieNode* node) {
35 if (node == NULL) return;
36 for (int i = 0; i < ALPHABET_SIZE; i++)
37 trie_free(node->children[i]);
38 free(node);
39}
40
41void trie_insert(TrieNode* root, const char* word) {
42 TrieNode* node = root;
43 while (*word) {
44 int idx = *word - 'a';
45 if (node->children[idx] == NULL)
46 node->children[idx] = trie_create_node();
47 node = node->children[idx];
48 node->count++;
49 word++;
50 }
51 node->is_end = true;
52}
53
54bool trie_search(TrieNode* root, const char* word) {
55 TrieNode* node = root;
56 while (*word) {
57 int idx = *word - 'a';
58 if (node->children[idx] == NULL)
59 return false;
60 node = node->children[idx];
61 word++;
62 }
63 return node->is_end;
64}
65
66bool trie_starts_with(TrieNode* root, const char* prefix) {
67 TrieNode* node = root;
68 while (*prefix) {
69 int idx = *prefix - 'a';
70 if (node->children[idx] == NULL)
71 return false;
72 node = node->children[idx];
73 prefix++;
74 }
75 return true;
76}
77
78int trie_count_prefix(TrieNode* root, const char* prefix) {
79 TrieNode* node = root;
80 while (*prefix) {
81 int idx = *prefix - 'a';
82 if (node->children[idx] == NULL)
83 return 0;
84 node = node->children[idx];
85 prefix++;
86 }
87 return node->count;
88}
89
90/* =============================================================================
91 * 2. ๋จ์ด ์ญ์
92 * ============================================================================= */
93
94bool trie_delete_helper(TrieNode* node, const char* word, int depth) {
95 if (node == NULL) return false;
96
97 if (*word == '\0') {
98 if (!node->is_end) return false;
99 node->is_end = false;
100
101 /* ์์์ด ์์ผ๋ฉด ์ญ์ ๊ฐ๋ฅ */
102 for (int i = 0; i < ALPHABET_SIZE; i++) {
103 if (node->children[i]) return false;
104 }
105 return true;
106 }
107
108 int idx = *word - 'a';
109 if (trie_delete_helper(node->children[idx], word + 1, depth + 1)) {
110 free(node->children[idx]);
111 node->children[idx] = NULL;
112
113 /* ํ์ฌ ๋
ธ๋๋ ์ญ์ ๊ฐ๋ฅํ์ง ํ์ธ */
114 if (!node->is_end) {
115 for (int i = 0; i < ALPHABET_SIZE; i++) {
116 if (node->children[i]) return false;
117 }
118 return true;
119 }
120 }
121
122 return false;
123}
124
125void trie_delete(TrieNode* root, const char* word) {
126 trie_delete_helper(root, word, 0);
127}
128
129/* =============================================================================
130 * 3. ์๋์์ฑ
131 * ============================================================================= */
132
133void autocomplete_helper(TrieNode* node, char* prefix, int prefix_len,
134 char** results, int* count, int max_results) {
135 if (*count >= max_results) return;
136
137 if (node->is_end) {
138 results[*count] = malloc(prefix_len + 1);
139 strcpy(results[*count], prefix);
140 (*count)++;
141 }
142
143 for (int i = 0; i < ALPHABET_SIZE; i++) {
144 if (node->children[i]) {
145 prefix[prefix_len] = 'a' + i;
146 prefix[prefix_len + 1] = '\0';
147 autocomplete_helper(node->children[i], prefix, prefix_len + 1,
148 results, count, max_results);
149 }
150 }
151}
152
153char** autocomplete(TrieNode* root, const char* prefix, int* result_count, int max_results) {
154 char** results = malloc(max_results * sizeof(char*));
155 *result_count = 0;
156
157 /* ์ ๋์ฌ ๋
ธ๋ ์ฐพ๊ธฐ */
158 TrieNode* node = root;
159 char* current_prefix = malloc(100);
160 strcpy(current_prefix, prefix);
161 int prefix_len = strlen(prefix);
162
163 while (*prefix) {
164 int idx = *prefix - 'a';
165 if (node->children[idx] == NULL) {
166 free(current_prefix);
167 return results;
168 }
169 node = node->children[idx];
170 prefix++;
171 }
172
173 autocomplete_helper(node, current_prefix, prefix_len, results, result_count, max_results);
174 free(current_prefix);
175 return results;
176}
177
178/* =============================================================================
179 * 4. ์์ผ๋์นด๋ ๊ฒ์
180 * ============================================================================= */
181
182bool wildcard_search_helper(TrieNode* node, const char* word) {
183 if (*word == '\0')
184 return node->is_end;
185
186 if (*word == '.') {
187 for (int i = 0; i < ALPHABET_SIZE; i++) {
188 if (node->children[i] && wildcard_search_helper(node->children[i], word + 1))
189 return true;
190 }
191 return false;
192 }
193
194 int idx = *word - 'a';
195 if (node->children[idx] == NULL)
196 return false;
197 return wildcard_search_helper(node->children[idx], word + 1);
198}
199
200bool wildcard_search(TrieNode* root, const char* pattern) {
201 return wildcard_search_helper(root, pattern);
202}
203
204/* =============================================================================
205 * 5. XOR ํธ๋ผ์ด (๋นํธ ํธ๋ผ์ด)
206 * ============================================================================= */
207
208typedef struct XORTrieNode {
209 struct XORTrieNode* children[2];
210} XORTrieNode;
211
212XORTrieNode* xor_trie_create_node(void) {
213 XORTrieNode* node = malloc(sizeof(XORTrieNode));
214 node->children[0] = NULL;
215 node->children[1] = NULL;
216 return node;
217}
218
219void xor_trie_free(XORTrieNode* node) {
220 if (node == NULL) return;
221 xor_trie_free(node->children[0]);
222 xor_trie_free(node->children[1]);
223 free(node);
224}
225
226void xor_trie_insert(XORTrieNode* root, int num) {
227 XORTrieNode* node = root;
228 for (int i = 31; i >= 0; i--) {
229 int bit = (num >> i) & 1;
230 if (node->children[bit] == NULL)
231 node->children[bit] = xor_trie_create_node();
232 node = node->children[bit];
233 }
234}
235
236int xor_trie_max_xor(XORTrieNode* root, int num) {
237 XORTrieNode* node = root;
238 int result = 0;
239
240 for (int i = 31; i >= 0; i--) {
241 int bit = (num >> i) & 1;
242 int want = 1 - bit; /* ๋ฐ๋ ๋นํธ ์ ํธ */
243
244 if (node->children[want]) {
245 result |= (1 << i);
246 node = node->children[want];
247 } else if (node->children[bit]) {
248 node = node->children[bit];
249 } else {
250 break;
251 }
252 }
253
254 return result;
255}
256
257int find_max_xor_pair(int arr[], int n) {
258 XORTrieNode* root = xor_trie_create_node();
259 int max_xor = 0;
260
261 xor_trie_insert(root, arr[0]);
262
263 for (int i = 1; i < n; i++) {
264 int xor_val = xor_trie_max_xor(root, arr[i]);
265 if (xor_val > max_xor) max_xor = xor_val;
266 xor_trie_insert(root, arr[i]);
267 }
268
269 xor_trie_free(root);
270 return max_xor;
271}
272
273/* =============================================================================
274 * 6. ์ต์ฅ ๊ณตํต ์ ๋์ฌ
275 * ============================================================================= */
276
277char* longest_common_prefix(char* strs[], int n) {
278 if (n == 0) return "";
279
280 TrieNode* root = trie_create_node();
281
282 /* ์ฒซ ๋ฒ์งธ ๋ฌธ์์ด๋ง ์ฝ์
*/
283 trie_insert(root, strs[0]);
284
285 char* lcp = malloc(strlen(strs[0]) + 1);
286 int lcp_len = 0;
287
288 TrieNode* node = root;
289 const char* first = strs[0];
290
291 while (*first) {
292 int idx = *first - 'a';
293
294 /* ๋ถ๊ธฐ๊ฐ ์๊ฑฐ๋ ๋จ์ด ๋์ด๋ฉด ์ค๋จ */
295 int child_count = 0;
296 for (int i = 0; i < ALPHABET_SIZE; i++) {
297 if (node->children[i]) child_count++;
298 }
299
300 if (child_count != 1 || node->is_end)
301 break;
302
303 /* ๋ค๋ฅธ ๋ฌธ์์ด์์ ์ด ์ ๋์ฌ ํ์ธ */
304 bool all_match = true;
305 for (int i = 1; i < n; i++) {
306 if (strs[i][lcp_len] != *first) {
307 all_match = false;
308 break;
309 }
310 }
311
312 if (!all_match) break;
313
314 lcp[lcp_len++] = *first;
315 node = node->children[idx];
316 first++;
317 }
318
319 lcp[lcp_len] = '\0';
320 trie_free(root);
321 return lcp;
322}
323
324/* =============================================================================
325 * ํ
์คํธ
326 * ============================================================================= */
327
328int main(void) {
329 printf("============================================================\n");
330 printf("ํธ๋ผ์ด (Trie) ์์ \n");
331 printf("============================================================\n");
332
333 /* 1. ๊ธฐ๋ณธ ํธ๋ผ์ด */
334 printf("\n[1] ๊ธฐ๋ณธ ํธ๋ผ์ด ์ฐ์ฐ\n");
335 TrieNode* trie = trie_create_node();
336
337 const char* words[] = {"apple", "app", "apricot", "banana", "band"};
338 printf(" ์ฝ์
: apple, app, apricot, banana, band\n");
339 for (int i = 0; i < 5; i++)
340 trie_insert(trie, words[i]);
341
342 printf(" search('app'): %s\n", trie_search(trie, "app") ? "true" : "false");
343 printf(" search('apt'): %s\n", trie_search(trie, "apt") ? "true" : "false");
344 printf(" startsWith('ap'): %s\n", trie_starts_with(trie, "ap") ? "true" : "false");
345 printf(" countPrefix('ap'): %d\n", trie_count_prefix(trie, "ap"));
346
347 /* 2. ์ญ์ */
348 printf("\n[2] ๋จ์ด ์ญ์ \n");
349 printf(" delete('app')\n");
350 trie_delete(trie, "app");
351 printf(" search('app'): %s\n", trie_search(trie, "app") ? "true" : "false");
352 printf(" search('apple'): %s\n", trie_search(trie, "apple") ? "true" : "false");
353
354 /* 3. ์๋์์ฑ */
355 printf("\n[3] ์๋์์ฑ\n");
356 int result_count;
357 char** suggestions = autocomplete(trie, "ap", &result_count, 10);
358 printf(" 'ap'๋ก ์์ํ๋ ๋จ์ด:\n");
359 for (int i = 0; i < result_count; i++) {
360 printf(" - %s\n", suggestions[i]);
361 free(suggestions[i]);
362 }
363 free(suggestions);
364
365 /* 4. ์์ผ๋์นด๋ */
366 printf("\n[4] ์์ผ๋์นด๋ ๊ฒ์\n");
367 printf(" search('b.nd'): %s\n", wildcard_search(trie, "b.nd") ? "true" : "false");
368 printf(" search('b..d'): %s\n", wildcard_search(trie, "b..d") ? "true" : "false");
369 printf(" search('.pple'): %s\n", wildcard_search(trie, ".pple") ? "true" : "false");
370
371 trie_free(trie);
372
373 /* 5. XOR ํธ๋ผ์ด */
374 printf("\n[5] XOR ํธ๋ผ์ด - ์ต๋ XOR ์\n");
375 int arr[] = {3, 10, 5, 25, 2, 8};
376 printf(" ๋ฐฐ์ด: [3, 10, 5, 25, 2, 8]\n");
377 printf(" ์ต๋ XOR: %d\n", find_max_xor_pair(arr, 6));
378
379 /* 6. ์ต์ฅ ๊ณตํต ์ ๋์ฌ */
380 printf("\n[6] ์ต์ฅ ๊ณตํต ์ ๋์ฌ\n");
381 char* strs[] = {"flower", "flow", "flight"};
382 char* lcp = longest_common_prefix(strs, 3);
383 printf(" [\"flower\", \"flow\", \"flight\"]\n");
384 printf(" LCP: '%s'\n", lcp);
385 free(lcp);
386
387 /* 7. ๋ณต์ก๋ */
388 printf("\n[7] ํธ๋ผ์ด ๋ณต์ก๋ (m = ๋ฌธ์์ด ๊ธธ์ด)\n");
389 printf(" | ์ฐ์ฐ | ์๊ฐ๋ณต์ก๋ |\n");
390 printf(" |--------------|------------|\n");
391 printf(" | ์ฝ์
| O(m) |\n");
392 printf(" | ๊ฒ์ | O(m) |\n");
393 printf(" | ์ ๋์ฌ ๊ฒ์ | O(m) |\n");
394 printf(" | ์ญ์ | O(m) |\n");
395 printf(" | ๊ณต๊ฐ | O(n * m) |\n");
396
397 printf("\n============================================================\n");
398
399 return 0;
400}