[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/

posted @ 2018-08-14 09:42  real_l  阅读(362)  评论(0编辑  收藏  举报