首页 > 代码库 > Phone List
Phone List
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:
- Emergency 911
- Alice 97 625 999
- 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
2391197625999911254265113123401234401234598346
Sample Output
NOYES
#include<stdio.h>#include<stdlib.h>#define MAX 10using namespace std;bool flag;typedef struct Trie_Node{ bool isphone; struct Trie_Node *next[MAX];}Trie;void insert(Trie *root,char *phone)//插入 { Trie *p=root; while(*phone!=‘\0‘) { if(p->next[*phone-48]==NULL) { Trie *temp=(Trie *)malloc(sizeof(Trie)); temp->isphone=false; for(int i=0;i<MAX;i++) { temp->next[i]=NULL; } p->next[*phone-48]=temp; } if(p->isphone==true) flag=true; p=p->next[*phone-48]; phone++; } p->isphone=true; for(int i=0;i<MAX;i++) { if(p->next[i]!=NULL) { flag=true; break; } }}void del(Trie *root)//删除 { for(int i=0;i<MAX;i++) { if(root->next[i]!=NULL) { del(root->next[i]); } } free(root);}int main(int argc,char *argv[]){ int t; scanf("%d",&t); while(t--) { int i; int n; char phone[11]; Trie *root=(Trie *)malloc(sizeof(Trie)); root->isphone=false; flag=false; for(i=0;i<MAX;i++) { root->next[i]=NULL; } scanf("%d",&n); for(i=0;i<n;i++) { scanf("%s",phone); if(flag!=true) { insert(root,phone); } } if(flag==true) printf("NO\n"); else printf("YES\n"); del(root); } return 0;}
又一代码:
#include<stdio.h>#include<string.h>#include<stdlib.h>struct telnumber{ struct telnumber *child[10]; bool isroot;};struct telnumber *root;void initial(struct telnumber *node){ int i; for(i=0;i<10;i++) node->child[i]=NULL; node->isroot=0;}void freedom(struct telnumber *p){ int i; for(i=0;i<10;i++) if(p->child[i]!=NULL) freedom(p->child[i]); free(p);}bool insert(char *source){ int i,len; bool preinsert,postinsert; struct telnumber *curent,*newnode; preinsert=postinsert=0; len=strlen(source); curent=root; for(i=0;i<len;i++) { if(curent->child[source[i]-‘0‘]!=NULL) { curent=curent->child[source[i]-‘0‘]; if(curent->isroot==1) preinsert=1; } else//如果前缀在后面插入,则没有新节点申请 { newnode=(struct telnumber *)malloc(sizeof(struct telnumber)); initial(newnode); curent->child[source[i]-‘0‘]=newnode; curent=newnode; postinsert=1;//表示申请过新节点,第二种情况不可能发生了 } } curent->isroot=1; if(preinsert||!postinsert) return 0;//返回0表示有前缀发生 else return 1;//无前缀发生} int main(){ int T,n,i; bool flag; char table[12]; scanf("%d",&T); while(T--) { scanf("%d",&n); root=(struct telnumber *)malloc(sizeof(struct telnumber)); initial(root); for(i=0,flag=1;i<n;i++) { scanf("%s",table); if(insert(table)==0) flag=0; } if(flag==1) printf("YES\n"); else printf("NO\n"); freedom(root); } return 0;}
另一种思路,就是先对电话号码序列进行排序,然后判断相邻的两个号码是否符合条件即可。这种思路利用了一种性质:
#include<iostream>#include<algorithm>#include<cstring>using namespace std;char phone[10000][11];int cmp(const void* a,const void* b){ return strcmp((char*)a,(char*)b);}int main(void){ int t; scanf("%d",&t); while(t--) { int i,n; bool flag=false; scanf("%d",&n); for(i=0;i<n;i++) { scanf("%s",phone[i]); } qsort(phone,n,sizeof(phone[0]),cmp); for(i=0;i<n-1;i++) { if(strncmp(phone[i],phone[i+1],strlen(phone[i]))==0) { flag=true; break; } } if(flag==false) printf("YES\n"); else printf("NO\n"); } return 0;}
@@@@if(strncmp(phone[i],phone[i+1],strlen(phone[i]))==0)//比较字符串的前strlen长度的字符
字典树!新番字典树第一弹,主要是套模板,在建树过程中对每个号码的尾部进行标记,每输入一个号码分两种情况讨论,如果这个号码是之前输入的某个号码的前缀,或者这个号码的前缀是之前输入的某个号码,均不符合要求,输出NO,否则输出YES。注意每组判断输出完毕后释放这个Trie树的空间,再重新构建树,否则会MLE。
字典树:
又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希表高
3编辑
串的快速检索
“串”排序
最长公共前缀
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 | #defineMAX26//字符集大小 typedefstructTrieNode { intnCount; //记录该字符出现次数 structTrieNode*next[MAX]; }TrieNode; TrieNodeMemory[1000000]; intallocp=0; /*初始化*/ voidInitTrieRoot(TrieNode**pRoot) { *pRoot=NULL; } /*创建新结点*/ TrieNode*CreateTrieNode() { inti; TrieNode*p; p=&Memory[allocp++]; p->nCount=1; for (i=0;i<MAX;i++) { p->next[i]=NULL; } returnp; } /*插入*/ voidInsertTrie(TrieNode**pRoot, char *s) { inti,k; TrieNode*p; if (!(p=*pRoot)) { p=*pRoot=CreateTrieNode(); } i=0; while (s[i]) { k=s[i++]- ‘a‘ ; //确定branch if (p->next[k]) p->next[k]->nCount++; else p->next[k]=CreateTrieNode(); p=p->next[k]; } } //查找 intSearchTrie(TrieNode**pRoot, char *s) { TrieNode*p; inti,k; if (!(p==*pRoot)) { return0; } i=0; while (s[i]) { k=s[i++]- ‘a‘ ; if (p->next[k]==NULL)return0; p=p->next[k]; } returnp->nCount; } |