[POJ3630] Phone List
传送门 - > \(POJ3630\)
题目描述
给定一个电话号码列表,确定它是否一致,因为没有号码是另一个号码的前缀。假设电话目录列出了这些号码:
Emergency 911
Alice 97 625 999
Bob 91 12 54 26
在这种情况下,不可能打电话给Bob,因为一旦您拨了Bob电话号码的前三位数,中央就会将您的电话直接打到紧急线路。所以这个名单不一致。
输入
第一行输入给出一个整数,1≤t≤40,测试用例数。每个测试用例从n个电话号码开始,在一个单独的行上,1≤n≤10000。然后跟随n行每条线上有一个唯一的电话号码。电话号码是一个最多十位数的序列。
输出
对于每个测试用例,如果列表一致,输出“是”,否则输出“否”。
样例输入
2
3
911
97625999
91125426
5
113
12340
123440
12345
98346
样例输出
NO
YES
题解
trie树裸题
在插入的时候标记一下当前单词的结尾
在检索的时候分两种情况,设当前字符串长度为len,前len-1位如果有标记就代表有前缀,不合法
若第len位标记数量大于等于2,则代表有重复字符串,不合法
#include<cstdio>
#include<cstring>
#include<cmath>
#define Min(a,b) (a)<(b)?(a):(b)
#define Max(a,b) (a)>(b)?(a):(b)
#define in(i) (i=read())
using namespace std;
int read() {
int ans=0,f=1; char i=getchar();
while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
while(i>='0' && i<='9') {ans=(ans<<1)+(ans<<3)+i-'0'; i=getchar();}
return ans*f;
}
int T,tot,flag;
int trie[1000010][10],ed[1000010];
char s[10010][20];
void insert(char *str) {
int len=strlen(str),p=0;
for(int i=0;i<len;i++) {
int c=str[i]-'0';
if(!trie[p][c]) trie[p][c]=++tot;
p=trie[p][c];
} ed[p]++;
}
void find(char *str) {
if(!flag) return;
int len=strlen(str),p=0;
for(int i=0;i<len;i++) {
int c=str[i]-'0';
if(ed[p]) {flag=0;return;}
p=trie[p][c];
}
if(ed[p]>=2) flag=0;
}
int main()
{
in(T);
while(T--) {
int n; in(n);
tot=0; flag=1;
memset(ed,0,sizeof(ed));
memset(trie,0,sizeof(trie));
for(int i=1;i<=n;i++) {
scanf("%s",s[i]);
insert(s[i]);
}
for(int i=1;i<=n;i++) find(s[i]);
puts(flag?"YES":"NO");
}
}
博主蒟蒻,随意转载.但必须附上原文链接
http://www.cnblogs.com/real-l/
博主蒟蒻,随意转载.但必须附上原文链接
http://www.cnblogs.com/real-l/
http://www.cnblogs.com/real-l/