[Trie] POJ3630 Phone List

Phone List

题目描述

给定一个电话号码列表,确定它是否一致,因为没有号码是另一个号码的前缀。假设电话目录列出了这些号码:
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/

猜你喜欢

转载自www.cnblogs.com/real-l/p/9472724.html