HDU 1671 Phone list (Tire tree)

题意:

      给定一个电话列表,判断是否出现一个号码是另一个号码前缀的情况,如果有输出“NO”否则输出“YES”

解法:

      字典树

没有考虑到的情况:

      给定的电话号码系列不适字典序的,如果前缀号码出现在后面,这程序判断失误。

如:

   911

   911123

对于这组数据可以得到正确的答案

   911123

   911

对于这组数据就判断失误了。

后面想到了这种情况,就给程序打了个补丁,用一个标记变量flag来标记插入过程中是否有重新创建节点。

 

AC代码如下:

/* Author: ACb0y Date: 2010年12月5日16:24:34 ProblemID: HDU 1671 Phone list Type: Tire tree Result: 3284412 2010-12-05 16:21:00 Accepted 1671 296MS 3300K 1338 B C++ ACb0y */ #include <stdio.h> #include <malloc.h> #include <string.h> struct node { node * child[10]; //标记是否为一个号码的结束 int if_end; }; node * root; int insert(char * str) { node * cur = root; node * pnew = NULL; int length = strlen(str); //用来标记在插入的过程中是否有重新构造节点。 int flag = 1; for(int i = 0; i < length; ++i) { int pos = str[i] - '0'; if (cur->child[pos] == NULL) { pnew = (node *)malloc(sizeof(node)); memset(pnew->child, 0, sizeof(node * [10])); pnew->if_end = 0; cur->child[pos] = pnew; flag = 0; } else if (cur->child[pos]->if_end) { return 0; } cur = cur->child[pos]; } cur->if_end = 1; //如果构造中没有重新构造过节点,则说明 //之前的号码出现过。 if (flag) { return 0; } return 1; } void clear(node * root) { if (root->if_end) { free(root); } else { for (int i = 0; i < 10; ++i) { if (root->child[i] != NULL) { clear(root->child[i]); } } free(root); } } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int cas; scanf("%d", &cas); while (cas--) { int n; int flag = 0; char str[15]; scanf("%d", &n); root = (node *)malloc(sizeof(node)); memset(root->child, 0, sizeof(node * [10])); root->if_end = 0; for(int i = 0; i < n; ++i) { scanf("%s", str); if (!flag && !insert(str)) { flag = 1; } } if (flag) { printf("NO/n"); } else { printf("YES/n"); } clear(root); } return 0; }

 

你可能感兴趣的:(list,tree,null,insert,电话,2010)