POJ 3630 Phone List/POJ 1056 【字典树】


http://poj.org/problem?id=3630
POJ 3630 Phone List
大意:电话簿中有n个电话号码,判断这些号码是否合法。
若某个电话号码是另一个电话号码的前缀,则该号码簿非法
分析:字典树即可
注意点,字典树在插入过程中新建节点会超时,故节点用数组的方式存储

网上看到一个风格较好的代码,模仿了一下写的,原始网站http://www.cnblogs.com/sysuwhj/archive/2010/11/17/1880328.html

View Code
1 /*
2 http://poj.org/problem?id=3630
3 POJ 3630 Phone List
4 大意:电话簿中有n个电话号码,判断这些号码是否合法。
5 若某个电话号码是另一个电话号码的前缀,则该号码簿非法
6 分析:字典树即可
7 注意点,字典树在插入过程中新建节点会超时,故节点用数组的方式存储
8 */
9
10 #include<stdio.h>
11 #include<string.h>
12 const int N = 10;//单个节点子树的个数
13 const int M = 100000;//字典树中最多会出现的子树个数
14 //字典树的节点
15 struct Trie_node
16 {
17 Trie_node *next[N];
18 bool isTail;//标记当前字符是否位于某个串的尾部
19 Trie_node()
20 {
21 isTail = false;
22 memset(next,NULL,sizeof(next));
23 }
24 };
25
26 Trie_node node[M];
27
28 //字典树类
29 class Trie
30 {
31 public:
32 Trie();
33 void clear();//将原有的信息清空
34 bool insert(char *);//插入某字符串
35
36 private:
37 Trie_node *root;//树的根节点
38 int nodeNum;//树中实际出现的节点数
39 };
40
41 Trie::Trie()
42 {
43 root = &node[0];
44 nodeNum = 1;
45 }
46
47 //将当前字典树中的所有节点信息清空
48 void Trie::clear()
49 {
50 int i;
51 for(i=0;i<nodeNum;i++)
52 {
53 memset(node[i].next,NULL,sizeof(node[i].next));
54 node[i].isTail = false;
55 }
56
57 nodeNum = 1;//清空时一定要注意这一步!!!!!!
58 }
59
60 //在当前树中插入word字符串,若出现非法,返回false
61 bool Trie::insert( char *word)
62 {
63 Trie_node *p = root;
64 while(*word)
65 {
66 //if(p->isTail)return false;//若当前节点已是某串的结尾
67 int curword = *word - '0';
68 if(p->next[curword]==NULL)
69 {
70 p->next[curword] = &node[nodeNum++];
71 }
72 p = p->next[curword];
73 if(p->isTail)return false;//某串是当前串的前缀
74 word++;//指针下移
75 }
76
77 p->isTail = true;//标记当前串已是结尾
78
79 //判断当前串是否是某个串的前缀
80 for(int i = 0;i < N;i++)
81 if(p->next[i]!=NULL)
82 return false;
83 return true;
84 }
85
86
87
88 char word[M];
89 int main()
90 {
91 int T;
92 Trie myTrie;
93 scanf("%d",&T);
94 while(T--)
95 {
96 int n;
97 scanf("%d",&n);
98 myTrie.clear();
99
100 bool islegal = true;
101 while(n--)
102 {
103 scanf("%s",word);
104 if(islegal==false)continue;
105 islegal = myTrie.insert(word);
106 }
107
108 if(islegal)
109 printf("YES\n");
110 else
111 printf("NO\n");
112 }
113 return 0;
114 }


POJ 1056 IMMEDIATE DECODABILITY
http://poj.org/problem?id=1056
求若干01字符串集是否非法。
若集合中出现某一串是另一串的前缀,那么该集合非法
分析:字典树

View Code
#include<stdio.h>
#include
<string.h>
const int N = 2;//单个节点子树的个数
const int M = 100000;//字典树中最多会出现的子树个数
//字典树的节点
struct Trie_node
{
Trie_node
*next[N];
bool isTail;//标记当前字符是否位于某个串的尾部
Trie_node()
{
isTail
= false;
memset(next,NULL,
sizeof(next));
}
};

Trie_node node[M];

//字典树类
class Trie
{
public:
Trie();
void clear();//将原有的信息清空
bool insert(char *);//插入某字符串

private:
Trie_node
*root;//树的根节点
int nodeNum;//树中实际出现的节点数
};

Trie::Trie()
{
root
= &node[0];
nodeNum
= 1;
}

//将当前字典树中的所有节点信息清空
void Trie::clear()
{
int i;
for(i=0;i<nodeNum;i++)
{
memset(node[i].next,NULL,
sizeof(node[i].next));
node[i].isTail
= false;
}

nodeNum
= 1;//清空时一定要注意这一步!!!!!!
}

//在当前树中插入word字符串,若出现非法,返回false
bool Trie::insert( char *word)
{
Trie_node
*p = root;
while(*word)
{
//if(p->isTail)return false;//若当前节点已是某串的结尾
int curword = *word - '0';
if(p->next[curword]==NULL)
{
p
->next[curword] = &node[nodeNum++];
}
p
= p->next[curword];
if(p->isTail)return false;//某串是当前串的前缀
word++;//指针下移
}

p
->isTail = true;//标记当前串已是结尾

//判断当前串是否是某个串的前缀
for(int i = 0;i < N;i++)
if(p->next[i]!=NULL)
return false;
return true;
}



char word[M];
int main()
{
int T = 0;
Trie myTrie;
//scanf("%d",&T);
bool islegal = true;
while(scanf("%s",word)!=EOF)
{
if(strcmp(word,"9")==0)
{
if(islegal)
printf(
"Set %d is immediately decodable\n",++T);
else
printf(
"Set %d is not immediately decodable\n",++T);
myTrie.clear();
islegal
= true;
continue;
}

if(islegal==false)continue;
islegal
= myTrie.insert(word);
}
return 0;
}


 

posted @ 2011-03-16 19:29  AndreMouche  阅读(635)  评论(0编辑  收藏  举报