poj 3630 Phone List(依旧Trie~)

给你几个号码,判断是否其中有一个是另一个的前缀。

 

比如。 

 

911

9110000

 

那么911是9110000的前缀,输出NO。

 

 

 

思路是,用一个字典树存号码。输入一个插入一个。用malloc超时了,所以选择使用静态存储。

插入的时候,如果遇到节点flag不为0,那么说明已经有单词末尾到这个节点了,即已经有单词是现在插入单词的前缀了,标记下。

如果插完后节点的子指针还有不为空的,说民现在插入的单词是之前插入的某个单词的前缀。

比如插入,1129000,再插入112,到2结束,但是2的子指针9不为空,说明已经有单词前面和它一样而且比它长,标记。

另一种思路是,对字符串排序(按长度排,按strcmp都行),然后就不用判断第二种操作了。只可能是前面是后面的前缀。

 

 

 

 

900+MS.。。。险过= =。。

 

#include <stdio.h> #include <stdlib.h> #include <iostream> #include <string.h> using namespace std; typedef struct Trie{ int flag; Trie *child[10]; }Trie; Trie *p,node[1000000]; int con,cou; void init() { p = &node[0]; memset(node,'/0',sizeof(node)); con = 0; cou = 1; } void Build(char *a) { int len = strlen(a); Trie *head = p; for(int i=0; i<len; i++) { int ind = a[i] - '0'; if( head->child[ind] == NULL ) head->child[ind] = &node[cou++]; if( head->child[ind]->flag == 1 ) //如果中间有节点已经标记过了,说明到这个字母的地方已经有单词了 。 { con = 1; return; } head = head->child[ind]; } for(int i=0; i<10; i++) if( head->child[i] != NULL ) //如果这个单词完毕后子指针还有非空的,说明它可以是之前插入单词的前缀。 { con = 1; return; } if( head->flag == 1 ) // 标记单词末尾。 con = 1; else head->flag = 1; } int main(void) { int ncases,n; char str[12]; scanf("%d",&ncases); while( ncases-- ) { init(); scanf("%d",&n); for(int i=0; i<n; i++) { scanf("%s",str); if( !con ) Build(str); } if( con ) printf("NO/n"); else printf("YES/n"); } return 0; }  

你可能感兴趣的:(list,struct,null,存储,Build)