原题
Phone List
Time Limit: 1000MS Memory Limit: 32768KB 64bit IO Format: %I64d & %I64u
Description
Given a list of phone numbers, determine if it is consistent in the sense that no number is the prefix of another. Let’s say the phone catalogue listed these numbers:
1. Emergency 911
2. Alice 97 625 999
3. Bob 91 12 54 26
In this case, it’s not possible to call Bob, because the central would direct your call to the emergency line as soon as you had dialled the first three digits of Bob’s phone number. So this list would not be consistent.
Input
The first line of input gives a single integer, 1 <= t <= 40, the number of test cases. Each test case starts with n, the number of phone numbers, on a separate line, 1 <= n <= 10000. Then follows n lines with one unique phone number on each line. A phone
number is a sequence of at most ten digits.
Output
For each test case, output “YES” if the list is consistent, or “NO” otherwise.
Sample Input
2
3
911
97625999
91125426
5
113
12340
123440
12345
98346
Sample Output
NO
YES
题意
与前缀编码有一点类似,本题是要判断给出的号码是否为”前缀号码“(即任何一个号码都不能是其他号码的前缀)。
涉及知识及算法
字典树、前缀编码详见百度百科
法1:构造字典树,标记号码的末尾结点,完成构造后在树中搜索判断是否在叶子结点之外还有标记。
法2:在构造的同时判断。对“911 91125426”判断后者插入时路径上是否有标记,对“91125426 911”判断后者是否生成新结点。
法3:(巧解) 首先将所有的号码当做 long long 型存入数组,读完后进行排序,再从小到大读出每个数,并用map进行标记以示这个数出现过,然后在对这个数不断进行除10操作,判断除10后的数有没有被标记,不过WA了,后来想想看应该是有些号码前面是0,这样就不行了,不过后来一想可以将所有的数前面都加个1不就解决了。。。。
——详见博主fszxwfy http://fszxwfy.blog.163.com/blog/static/44019308201282484625551/
在此就只贴上法2的代码了
代码
#include <iostream>
#include <cstdio>
#include <malloc.h>
#include <cstdlib>
#include <cstring>
using namespace std;
int flag,flag2;
typedef struct Trie_node
{
bool exist;
struct Trie_node* next[10];
}TrieNode,*Trie;
TrieNode* createTrieNode()
{
TrieNode* node=(TrieNode*)malloc(sizeof(TrieNode));
node->exist=false;
memset(node->next,0,sizeof(node->next));
return node;
}
void Trie_insert(Trie root,char* word)
{
Trie node=root;flag2=0;
char *p=word;
int id;
while(*p)
{
id=*p-'0';
if(node->next[id]!=NULL&&node->next[id]->exist) //法2的第一个判断
{
flag=1;
}
if(node->next[id]==NULL)
{
node->next[id]=createTrieNode(); flag2=1; //如果未生成新结点,则flag2=0
}
node=node->next[id];
++p;
}
if(!flag2) flag=1; //第二个判断
node->exist=true;
}
void Clear(Trie a) //释放内存
{
if(a==NULL) return;
else
{
for(int i=0;i<10;i++)
{
Clear(a->next[i]);
}
}
free(a);
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
char str[11];
int kase;
cin>>kase;
while(kase--)
{
Trie root=createTrieNode();
flag=0;
int Count;
cin>>Count;
for(int i=0;i<Count;i++)
{
scanf("%s",str);
Trie_insert(root,str);
//cout<<"insert success"<<endl;
}
if(flag) cout<<"NO"<<endl;
else cout<<"YES"<<endl;
Clear(root);
//cout<<"Clear success!"<<endl;
}
return 0;
}