免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
论坛 程序设计 C/C++ trie树
最近访问板块 发新帖
查看: 3895 | 回复: 7
打印 上一主题 下一主题

trie树 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-01-03 12:09 |只看该作者 |倒序浏览
题目地址:http://www.soj.me/1426
以前直接排序加上做一些判断就AC了,现在想练练trie,可是一直没AC。代码如下:(大家顺便教我怎么结贴,一直没找到)

  1. #include <stdio.h>
  2. #include<stdlib.h>
  3. #include <string.h>
  4. #define MAX 11
  5. typedef struct node
  6. {
  7.     char data;
  8.     struct node *next[MAX];
  9.     int mrk;
  10. }node;

  11. void del(node *root);

  12. int main()
  13. {
  14.     int t, n;
  15.     scanf("%d", &t);
  16.     for(; t>0; t--)
  17.     {
  18.         int prefix = 0, cnt;
  19.         node *root = malloc(sizeof(node));
  20.         root->data = '#';//根节点就随便放个数据吧
  21.         memset(root->next, 0, sizeof(root->next));
  22.         root->mrk = 0;
  23.         scanf("%d", &n);
  24.         char nums[10000][11];
  25.         memset(nums, 0, sizeof(nums));
  26.         for(cnt=0; cnt<n; cnt++)
  27.             scanf("%s", nums[cnt]);

  28.         for(cnt=0; cnt<n; cnt++)//下面是进行插入不进行判断
  29.         {
  30.             node *s = root;
  31.             int i, len = strlen(nums[cnt]);
  32.             char *tmp = nums[cnt];
  33.             for(i=0; i<len; i++)//插入第i个字符串,并做判断
  34.             {
  35.                 if(s->mrk == 1)//发现有前缀,让prefix为1
  36.                 {
  37.                     printf("%s\n", nums[cnt]);
  38.                     printf("============\n");
  39.                     prefix = 1;
  40.                     break;
  41.                 }

  42.                 if(s->next[tmp[i]-'0'] == NULL)//插入
  43.                 {
  44.                     printf("ifififif\n");
  45.                     s->next[tmp[i]-'0'] = (node*)malloc(sizeof(node));
  46.                     s->next[tmp[i]-'0']->data = tmp[i];
  47.                     memset(s->next[tmp[i]-'0']->next, 0, sizeof(s->next[tmp[i]-'0']->next));
  48.                     s->next[tmp[i]-'0']->mrk = 0;
  49.                 }
  50.                 else
  51.                     s = s->next[tmp[i]-'0'];
  52.             }
  53.             if(prefix == 1)
  54.                 break;
  55.             s->mrk = 1;
  56.         }
  57.         printf("%s\n", prefix==1?"NO":"YES");
  58.         del(root);
  59.     }
  60.     return 0;
  61. }

  62. void del(node *root)
  63. {
  64.     if(root == NULL)
  65.         return;
  66.     int i;
  67.     for(i=0; i<MAX; i++)
  68.         del(root->next[i]);
  69.     free(root);
  70. }
复制代码

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
2 [报告]
发表于 2011-01-03 12:32 |只看该作者
回复 1# scott_lan


    你难道没发现,你只记录了结束的状态,但是没有记录”经过“的状态么?

比如说,假设现在有个号码911112,你在2处设置了”结束“,但是又来了个号码911,你在最后的1处是找不到mrk的,但是它的确是之前号码的前缀。

修改一下设置prefix的条件。如果发现当前的串结束了,并且当前的节点不是现在分配的,那么也算prefix=1。

论坛徽章:
89
水瓶座
日期:2014-04-01 08:53:31天蝎座
日期:2014-04-01 08:53:53天秤座
日期:2014-04-01 08:54:02射手座
日期:2014-04-01 08:54:15子鼠
日期:2014-04-01 08:55:35辰龙
日期:2014-04-01 08:56:36未羊
日期:2014-04-01 08:56:27戌狗
日期:2014-04-01 08:56:13亥猪
日期:2014-04-01 08:56:02亥猪
日期:2014-04-08 08:38:58程序设计版块每日发帖之星
日期:2016-01-05 06:20:00程序设计版块每日发帖之星
日期:2016-01-07 06:20:00
3 [报告]
发表于 2011-01-03 15:57 |只看该作者
我觉得还是递归实现比较爽。

论坛徽章:
0
4 [报告]
发表于 2011-01-03 16:24 |只看该作者
回复 3# fender0107401
递归实现?可不可以给个例子出来呢?

论坛徽章:
89
水瓶座
日期:2014-04-01 08:53:31天蝎座
日期:2014-04-01 08:53:53天秤座
日期:2014-04-01 08:54:02射手座
日期:2014-04-01 08:54:15子鼠
日期:2014-04-01 08:55:35辰龙
日期:2014-04-01 08:56:36未羊
日期:2014-04-01 08:56:27戌狗
日期:2014-04-01 08:56:13亥猪
日期:2014-04-01 08:56:02亥猪
日期:2014-04-08 08:38:58程序设计版块每日发帖之星
日期:2016-01-05 06:20:00程序设计版块每日发帖之星
日期:2016-01-07 06:20:00
5 [报告]
发表于 2011-01-03 16:27 |只看该作者
回复 4# scott_lan

你destroy整个树的时候不就是用的递归吗,插入新的entry的时候也可以用递归实现,

我感觉递归看着比较清楚。

论坛徽章:
0
6 [报告]
发表于 2011-01-03 16:44 |只看该作者
题目地址:http://www.soj.me/1426
删除不用递归还真不知道怎么搞,重新写了一下,AC了,谢谢2楼~还是没人说怎么结贴啊,杯具
顺便贴下自己的代码,也希望各位帮看看还可以怎么改进
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include<string.h>
  4. /*
  5.     只是对一些号码进行处理,0-9的一些组合,,刚好串最长可以是10,定义MAX=10
  6. */
  7. #define MAX 10

  8. typedef struct trie_node
  9. {
  10.     struct trie_node *nxt[MAX];//每个节点有MAX个孩子,trie的空间开支巨大
  11.     int mrk;//初始化为0,一个号码插入完整后置1,表示整个号码都插入trie了
  12. } trie_node;

  13. int insert(trie_node *root, char *number)
  14. {
  15.     if(root==NULL)
  16.         return 0;
  17.     trie_node *cur = root;
  18.     int prefix = 0, i, len=strlen(number);
  19.     for(i=0; i<len; i++)
  20.     {
  21.         /*
  22.             因为是判断是否有前缀,先要判断mrk是不是等于1了
  23.             当前节点的number[i]-'0'分支为NULL
  24.         */
  25.         if(cur->mrk != 1 && cur->nxt[number[i]-'0']==NULL)
  26.         {
  27.             //分配一个新结点并初始化,插入
  28.             cur->nxt[number[i]-'0'] = malloc(sizeof(trie_node));
  29.             cur->nxt[number[i]-'0']->mrk = 0;
  30.             memset(cur->nxt[number[i]-'0']->nxt, 0, sizeof(cur->nxt[number[i]-'0']->nxt));
  31.         }
  32.         /*
  33.             如果已经到号码尾部:比如先插入111,再插入11111
  34.             或要插入串已经到结尾:比如先插入11111,再插入111
  35.             表明有前缀存在
  36.         */
  37.         else if(cur->mrk==1 || i==len-1)
  38.         {
  39.             prefix = 1;
  40.             break;
  41.         }
  42.         cur = cur->nxt[number[i]-'0'];
  43.     }
  44.     if(prefix==1)
  45.         return 1;
  46.     cur->mrk = 1;
  47.     return 0;
  48. }

  49. void clr(trie_node *root)
  50. {
  51.     if(root==NULL)
  52.         return;
  53.     int i;
  54.     for(i=0; i<MAX; i++)
  55.         clr(root->nxt[i]);
  56.     free(root);
  57. }

  58. int main()
  59. {
  60.     int t;
  61.     scanf("%d", &t);
  62.     for(; t>0; t--)
  63.     {
  64.         trie_node *root = malloc(sizeof(trie_node));
  65.         root->mrk = 0;
  66.         memset(root->nxt, 0, sizeof(root->nxt));
  67.         int n,i, prefix = 0;
  68.         char numbers[10000][MAX];
  69.         scanf("%d", &n);
  70.         for(i=0; i<n; i++)
  71.             scanf("%s", numbers[i]);
  72.         for(i=0; i<n; i++)
  73.         {
  74.             prefix=insert(root, numbers[i]);
  75.             if(prefix)
  76.                 break;
  77.        }
  78.        printf("%s\n", prefix==1?"NO":"YES");
  79.        clr(root);
  80.     }
  81.     return 0;
  82. }
复制代码

论坛徽章:
0
7 [报告]
发表于 2011-01-04 11:29 |只看该作者

论坛徽章:
0
8 [报告]
发表于 2011-01-04 16:11 |只看该作者
回复 7# redor
考完试好好研究~
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP