HDU 1671 Phone List(字典树)
Phone List
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6772 Accepted Submission(s): 2307
Problem Description
Given a list of phone numbers, determine if it is consistent in the sense that no number is the prefix of another. Let’s say the phone catalogue listed these numbers:
1. Emergency 911
2. Alice 97 625 999
3. Bob 91 12 54 26
In this case, it’s not possible to call Bob, because the central would direct your call to the emergency line as soon as you had dialled the first three digits of Bob’s phone number. So this list would not be consistent.
Input
The first line of input gives a single integer, 1 <= t <= 40, the number of test cases. Each test case starts with n, the number of phone numbers, on a separate line, 1 <= n <= 10000. Then follows n lines with one unique phone number on each line. A phone number is a sequence of at most ten digits.
Output
For each test case, output “YES” if the list is consistent, or “NO” otherwise.
Sample Input
2
3
911
97625999
91125426
5
113
12340
123440
12345
98346
Sample Output
NO
YES
题目大意:就是给出一系列的字符串,判断有没有一个字符串是另一个字符串的前缀,没有输出YES,否则输出NO。
另外这道题要记得内存释放,否则提交后会超内存。
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 typedef struct _TrieTree 6 { 7 bool flag; 8 struct _TrieTree *next[10]; 9 10 }TrieNode; 11 12 TrieNode *CreateTrieTree() //创建字典树 13 { 14 TrieNode *node = (TrieNode *)malloc(sizeof(TrieNode)); 15 node->flag = false; 16 for(int i = 0; i < 10; i++) 17 node->next[i] = NULL; 18 19 return node; 20 } 21 22 void InsertTrieTree(TrieNode *root, char word[]) //插入字符串 23 { 24 TrieNode *p = root; 25 int length = strlen(word); 26 for(int i = 0; i < length; i++) 27 { 28 int index = word[i] - 48; 29 if(p->next[index] == NULL) 30 { 31 p->next[index] = CreateTrieTree(); 32 } 33 p = p->next[index]; 34 } 35 p->flag = true; 36 } 37 38 bool QueryTrieTree(TrieNode *root, char word[]) //查询字符串 39 { 40 TrieNode *p = root; 41 int length = strlen(word); 42 for(int i = 0; i < length; i++) 43 { 44 int index = word[i] - 48; 45 p = p->next[index]; 46 if(i != length - 1 && p->flag) 47 return false; 48 } 49 50 return true; 51 } 52 53 void FreeTrieTree(TrieNode *root) //递归释放每个字典树的内存 54 { 55 TrieNode *p = root; 56 if(p != NULL) 57 { 58 for(int i = 0; i < 10; i++) 59 { 60 if(p->next[i] != NULL) 61 FreeTrieTree(p->next[i]); 62 } 63 delete p; 64 p = NULL; 65 } 66 } 67 68 int main() 69 { 70 int T, n; 71 const int MAX_NUM = 10005; 72 char word[MAX_NUM][11]; 73 74 scanf("%d", &T); 75 while(T--) 76 { 77 TrieNode *root = CreateTrieTree(); 78 79 scanf("%d", &n); 80 getchar(); 81 for(int i = 0; i < n; i++) 82 { 83 scanf("%s", word[i]); 84 InsertTrieTree(root, word[i]); 85 } 86 87 bool bResult = true; 88 for(int i = 0; i < n; i++) 89 { 90 bResult = QueryTrieTree(root, word[i]); 91 if(!bResult) 92 break; 93 } 94 95 if(bResult) 96 printf("YES\n"); 97 else 98 printf("NO\n"); 99 100 FreeTrieTree(root); 101 } 102 103 return 0; 104 }
然后,看到网上有的是在插入的过程中进行判断的,若在插入的过程中就已经判断出来有不符合条件的前缀字符串,
则剩余的未输入的字符串就不再插入到字典树中,减少部分时间开销。
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 typedef struct _TrieTree 6 { 7 bool flag; 8 struct _TrieTree *next[10]; 9 10 }TrieNode; 11 12 TrieNode *CreateTrieTree() //创建字典树 13 { 14 TrieNode *node = (TrieNode *)malloc(sizeof(TrieNode)); 15 node->flag = false; 16 for(int i = 0; i < 10; i++) 17 node->next[i] = NULL; 18 19 return node; 20 } 21 22 bool InsertTrieTree(TrieNode *root, char word[]) //插入字符串 23 { 24 TrieNode *p = root; 25 int length = strlen(word); 26 for(int i = 0; i < length; i++) 27 { 28 int index = word[i] - 48; 29 if(p->next[index] == NULL) 30 { 31 p->next[index] = CreateTrieTree(); 32 } 33 p = p->next[index]; 34 if(p->flag) //有字符串是它的前缀 35 return false; 36 } 37 for(int i = 0; i < 10; i++) 38 if(p->next[i] != NULL) //它是别的字符串的前缀 39 return false; 40 41 p->flag = true; 42 return true; 43 } 44 45 void FreeTrieTree(TrieNode *root) //递归释放每个字典树的内存 46 { 47 TrieNode *p = root; 48 if(p != NULL) 49 { 50 for(int i = 0; i < 10; i++) 51 { 52 if(p->next[i] != NULL) 53 FreeTrieTree(p->next[i]); 54 } 55 free(p); 56 p = NULL; 57 } 58 } 59 60 int main() 61 { 62 int T, n; 63 const int MAX_NUM = 10005; 64 char word[MAX_NUM][11]; 65 66 scanf("%d", &T); 67 while(T--) 68 { 69 TrieNode *root = CreateTrieTree(); 70 71 bool bResult = true; 72 scanf("%d", &n); 73 getchar(); 74 for(int i = 0; i < n; i++) 75 { 76 scanf("%s", word[i]); 77 if(!bResult) //若插入的过程中,已判断不符合条件 78 continue; //就跳过,不再插入 79 if(!InsertTrieTree(root, word[i])) 80 bResult = false; 81 } 82 83 if(bResult) 84 printf("YES\n"); 85 else 86 printf("NO\n"); 87 88 FreeTrieTree(root); 89 } 90 91 return 0; 92 }
另外还有一种方法,先对所有字符串进行排序,然后比较相邻两个字符串,若前一个字符串是后一个字符串的前缀,
就输出NO,否则输出YES。
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 5 typedef struct _PHONE 6 { 7 char word[11]; 8 9 }PHONE; 10 11 int cmp(const void *a, const void *b) 12 { 13 return strcmp( (*(PHONE *)a).word, (*(PHONE *)b).word ); 14 } 15 16 int main() 17 { 18 int T, n; 19 const int MAX_NUM = 10005; 20 PHONE phone[MAX_NUM]; 21 22 scanf("%d", &T); 23 while(T--) 24 { 25 scanf("%d", &n); 26 for(int i = 0; i < n; i++) 27 scanf("%s", phone[i].word); 28 29 qsort(phone, n, sizeof(PHONE), cmp); 30 31 bool bResult = true; 32 for(int i = 0; i < n - 1; i++) 33 { 34 char *p = strstr(phone[i + 1].word, phone[i].word); 35 if(p != NULL) 36 { 37 bResult = false; 38 break; 39 } 40 } 41 if(bResult) 42 printf("YES\n"); 43 else 44 printf("NO\n"); 45 } 46 47 return 0; 48 }