题目背景
HDU1671
题目描述
给出一份电话号码列表,如果不存在有一个号码是另一个号码的前缀,我们就说这份电话号码列表是合法的。让我们看看如下号码列表:
1. Emergency 911
2. Alice 97625999
3. Bob 91125426
在这组号码中,我们不能拨通 Bob 的电话,因为当你按下 Bob 电话号码的前 3 个数字“911”时,电话局会把你的拨号连接到 Emergency 的线路。
所以这组号码是不合法的。
输入格式
有多组输入数据。
第一行输入一个正整数 t(1<=t<=40),表示数据组数。
每组数据第一行是一个正整数 n(1<=n<=10000),表示电话号码的数量。
接下来有 n 行,每行一个电话号码,每个电话号码是不超过 10 位的连续数字。
输出格式
对每组数据,如果电话号码列表合法,则输出“YES”,不合法则输出“NO”。
样例数据
输入
2
3
911
97625999
91125426
5
113
12340
123440
12345
98346
输出
NO
YES
分析: trie树模板
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
#include<queue>
#include<set>
using namespace std;
int getint()
{
int sum=0,f=1;
char ch;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-')
{
f=-1;
ch=getchar();
}
for(;ch>='0'&&ch<='9';ch=getchar())
sum=(sum<<3)+(sum<<1)+ch-48;
return sum*f;
}
struct node{
int son[10];
int num;
}trie[100005];
char s[10];
int tot=0,top=0;
int n,t,a[400005];
void build_trie()
{
int position=0;
int len=strlen(s);
for(int i=0;i<len;++i)
{
if(!trie[position].son[s[i]-'0'])
{
trie[position].son[s[i]-'0']=++tot;
}
position=trie[position].son[s[i]-'0'];
trie[position].num++;
}
a[++top]=position;
}
int main()
{
freopen("trie.in","r",stdin);
freopen("trie.out","w",stdout);
t=getint();
while(t--)
{
memset(trie,0,sizeof(trie));
memset(a,0,sizeof(a));
top=0;tot=0;
bool sign=0;
n=getint();
for(int i=1;i<=n;++i)
{
scanf("%s",s);
build_trie();
}
for(int i=1;i<=n;++i)
{
if(trie[a[i]].num>1)
sign=1;
}
if(sign)
cout<<"NO"<<endl;
else
cout<<"YES"<<endl;
}
return 0;
}
本题结。