HDU 1671 Phone List [字典树]

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1671

Phone List

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 28746    Accepted Submission(s): 9368

 

Problem 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

题意:给你若干个数字串,判断其中某一个数字串是否为另一个数字串的前缀

思路:先将所有的数字串插入数字字典树中,然后在依次查询每个数字串的末尾结点是否有子结点,若有则输出NO,否则输出YES

#include<iostream>
#include<string.h>
#include<cstdio>
using namespace std;
const int maxnode = 1e6 + 7;
const int CH = 26;
int ch[maxnode][CH];
int val[maxnode];
int sz ;      //结点总数  初始有一个零结点
char s[maxnode][27];
int idx(char c)
{
    return c - '0';//因为是数字字典树,若是字符字典树则要c-'a';或者c-'A'
}
int node()//新建结点
{
    memset(ch[sz], 0, sizeof(ch[sz]));//将U结点的子结点初始化
    val[sz] = 0;//为零则代表不是插入字符的最后一个
    return sz++;
}
void init()
{
    sz = 0;
    node();//新建一个根结点
}
void insert(char *s, int v)//结点的插入
{
    int u = 0;
    int n = strlen(s);
    for(int i = 0; i < n; i++)
    {
        int c = idx(s[i]);//字符是s[i]是不是结点U的子节点
        if(!ch[u][c])//若不是U结点的子结点 则要新建结点
        {
            ch[u][c] = node();
        }
        u = ch[u][c];//继续更新
    }
    val[u] = v;// 将最后一个结点的子结点标记
}
bool ffind(char *s)
{
    int u = 0;
    int n = strlen(s);
    for(int i = 0; i < n; i++)
    {
        int c = idx(s[i]);
        if(!ch[u][c])//如果 查询长度还没有n个 则代表所查询的字符串在当前的字典树中不存在
            return 0;
        u = ch[u][c];//继续更新 查找
    }
    //跳出循环后   只要查询该U的子结点是否存在即可
    bool flag = false;
    for(int i = 0; i < 10; i++)//因为只有10个数字
    {
        if(ch[u][i])//如果有子结点 代表该数字串为某一个串的前缀
        {
            flag = true;
            break;
        }
    }
    if(flag)
    {
        return true;
    }
    else
    {
        return false;
    }
}
int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        init();
        int n;
        scanf("%d", &n);
        for(int i = 0; i < n; i++)
        {
            scanf("%s", s[i]);
            insert(s[i], i + 1);
        }
        bool flag = true;
        for(int i = 0; i < n; i++)
        {
            if(ffind(s[i]))
            {
                printf("NO\n");
                flag = false;
                break;
            }
        }
        if(flag)
            printf("YES\n");
    }
    return 0;
}

 

posted @ 2019-07-27 09:30  是妖妖灵鸭  阅读(83)  评论(0编辑  收藏  举报