hdu1671 字典树记录前缀出现次数

来源:互联网 发布:淘宝上的凯威淘淘通讯 编辑:程序博客网 时间:2024/06/05 20:16
题意:
      给你一堆电话号,问你这些电话号后面有没有相互冲突的,冲突的条件是当前这个电话号是另一个电话号的前缀,比如有 123456789 123,那么这两个电话号就冲突了,直接输出NO。

思路:  

      说白了就是前缀匹配,也就是以当前字符串为前缀的字符串有几个,只要有一个或者更多那么就直接NO了,快速的判断前缀的问题我们可以直接字典树记录前缀,先把所有的字符串都存在字典里,然后在枚举每一个,只要有一个是前缀(不算自己)那么就直接NO了,这里要注意一点,每次都要把Tree的内存清空,不然不同的mallco不释放,测试数据多了就MLE了。


#include<stdio.h>#include<string.h>#include<stdlib.h>char str[10005][12];typedef struct Tree{    Tree *next[10];    int v;}Tree;Tree root;void Buid_Tree(char *str){    int len = strlen(str);    Tree *p = &root ,*q;    for(int i = 0 ;i < len ;i ++)    {        int id = str[i] - '0';        if(p -> next[id] == NULL)        {            q = (Tree *) malloc(sizeof(root));            q -> v = 1;            for(int j = 0 ;j < 10 ;j ++)            q -> next[j] = NULL;            p -> next[id] = q;            p = p -> next[id];        }        else        {            p = p -> next[id];            p -> v ++;        }      }}int Find(char *str){    int len = strlen(str);    Tree *p = &root;    for(int i = 0 ;i < len ;i ++)    {        int id = str[i] - '0';        p = p -> next[id];        if(p == NULL) return 0;    }    return p -> v;}bool solve(int n){    for(int i = 1 ;i <= n ;i ++)    if(Find(str[i]) != 1) return 0;    return 1;}int dealTree(Tree* T){    int i;    if(T==NULL)        return 0;    for(i=0;i<10;i++)    {        if(T->next[i]!=NULL)            dealTree(T->next[i]);    }    free(T);    return 0;}int main (){    int t ,n ,i;    scanf("%d" ,&t);    while(t--)    {         scanf("%d" ,&n);         for(i = 0 ;i < 10 ;i ++)         root.next[i] = NULL;         for(i = 1 ;i <= n ;i ++)         {            scanf("%s" ,str[i]);            Buid_Tree(str[i]);         }         if(solve(n)) puts("YES");         else puts("NO");         dealTree(&root);      }    return 0;}

0 0
原创粉丝点击