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 ;
}


 

你可能感兴趣的:(list)