HDU 1671 Phone List(字典树)
Phone List
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 22697 Accepted Submission(s):
7684
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.
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
Source
Recommend
有n个数字串, 检查这些串中是否存在一个字符串是另一个字符串的前缀。
一开我内存超MLE,想不明白!
还好最后想明白了,原来每一轮运行,由于之前申请的内存没有释放,所以会有累加,于是把根节点放在了循环里面申请,又在末尾部分写了个释放函数,结果wa了,原因是当发现有前缀时,还应输完,不能直接跳出。
还好最后想明白了,原来每一轮运行,由于之前申请的内存没有释放,所以会有累加,于是把根节点放在了循环里面申请,又在末尾部分写了个释放函数,结果wa了,原因是当发现有前缀时,还应输完,不能直接跳出。
字典树的方法:
1 #include <iostream> 2 #include <cstring> 3 #include <string> 4 #include <algorithm> 5 #include <cstdio> 6 using namespace std; 7 typedef struct nn 8 { 9 bool f = 0; 10 nn* nxt[10]; 11 }node; 12 13 node *root; 14 char a[15]; 15 16 node*builde() 17 { 18 node *p = (node*)malloc(sizeof(node)); 19 p->f = 0; 20 int i; 21 for (i = 0; i <= 9; i++) 22 { 23 p->nxt[i] = NULL; 24 } 25 return p; 26 } 27 28 bool insert(char *s) 29 { 30 int l = strlen(s); 31 int i; 32 node *p = root; 33 bool k = 1; 34 for (i = 0; i < l; i++) 35 { 36 if (p->nxt[s[i] - '0'] == NULL) 37 { 38 p->nxt[s[i] - '0'] = builde(); 39 k = 0; 40 } 41 p = p->nxt[s[i] - '0']; 42 if (p->f == 1) return 1;//之前有数字串是该串的子串 43 } 44 if (k) return 1;//没有申请过空间,说明该串是之前数字串的子串 45 p->f = 1; 46 return 0; 47 } 48 49 void freedom(node*p)//刚开始没释放内存MLE了 50 { 51 int i; 52 for (i = 0; i <= 9; i++) 53 { 54 if (p->nxt[i] != NULL) 55 { 56 freedom(p->nxt[i]); 57 } 58 } 59 free(p); 60 } 61 62 int main() 63 { 64 int t; 65 bool f = 0; 66 cin >> t; 67 while (t--) 68 { 69 int n; 70 cin >> n; 71 f = 0; 72 root = builde(); 73 while (n--) 74 { 75 cin >> a; 76 if (!f)//当发现有前缀时,剩下的直接输入就行了 77 {//刚开始没写,发现前缀就跳出,wa了好多次 78 f = insert(a); 79 } 80 } 81 if (f) cout << "NO"<<endl; 82 else cout << "YES"<<endl; 83 freedom(root); 84 } 85 return 0; 86 }
另一种:
可以使用字符串排序比较来做,因为通过排序,前缀子串肯定是与父串挨着的,嘿嘿,这样做,思路简单、代码量少,易理解
1 #include<iostream> 2 #include<string.h> 3 #include<algorithm> 4 using namespace std; 5 char a[10005][11]; 6 int cmp(const void *m,const void *n){ 7 return strcmp((char*)m,(char*)n); 8 } 9 int main(){ 10 int t;cin>>t; 11 while(t--){ 12 int n;cin>>n; 13 for(int i=0;i<n;i++) cin>>a[i]; 14 qsort(a,n,sizeof(a[0]),cmp); 15 bool flag=1; 16 for(int i=0;i<n-1&&flag;i++){ 17 if(strncmp(a[i],a[i+1],strlen(a[i]))==0) flag=0; 18 } 19 if(flag) cout<<"YES"; 20 else cout<<"NO"; 21 cout<<endl; 22 } 23 }