题意:给定若干电话号码,如果没有号码是其他号码的前缀,则输出YES,否则输出NO
思路:使用Trie树(字典树),用flag域标定当前节点是否为一个电话号码的末位。直接分配空间。
输入:
2
3
911
97625999
91125426
5
113
12340
123440
12345
98346
输出:
NO
YES
#include <stdio.h> #include <string.h> #define N 100005 char s[11]; typedef struct node{ struct node* next[10]; int flag; }tree; tree t[N]; tree *alloc,*root; int T,n; void init(){ int i; alloc = t; root = alloc++; root->flag = 0; for(i = 0;i<10;i++) root->next[i] = NULL; } int insert(){ int i,j,flag = 0; tree *p,*q; p = root; for(i = 0;s[i]!='\0';i++){ if(p->next[s[i]-'0']!=NULL){ if(p->next[s[i]-'0']->flag == 1)//说明存在一个号码是当前号码的前缀 return 0; }else{ flag = 1;//如果插入过程中建立了新节点,则当前号码必成立;否则说明当前号码是另一个号码的前缀 q = alloc++; for(j = 0;j<10;j++) q->next[j] = NULL; if(s[i+1]!='\0') q->flag = 0; else q->flag = 1; p->next[s[i]-'0'] = q; } p = p->next[s[i]-'0']; } if(!flag) return 0; return 1; } int main(){ freopen("a.txt","r",stdin); scanf("%d",&T); while(T--){ int flag = 0; init(); scanf("%d",&n); while(n--){ scanf("%s",s); if(flag) continue; if(!insert()) flag = 1; } if(flag) printf("NO\n"); else printf("YES\n"); } return 0; }
int insert(){ int i,j; tree *p,*q; p = root; for(i = 0;s[i]!='\0';i++){ if(p->next[s[i]-'0']!=NULL){ if(p->next[s[i]-'0']->flag == 1)//说明存在一个号码是当前号码的前缀 return 0; if(s[i+1] == '\0')//说明当前号码是另一个号码的前缀 return 0; }else{ q = alloc++; for(j = 0;j<10;j++) q->next[j] = NULL; if(s[i+1]!='\0') q->flag = 0; else q->flag = 1; p->next[s[i]-'0'] = q; } p = p->next[s[i]-'0']; } return 1; }