POJ 3630

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40924940/article/details/84072945

这道题目依旧是 字典树题目

大意:

目前有 t 组数据, n 个电话号码,如果拨打号码的时候 先拨通了某个号码,那么这一串号码就无法全部拨通,

举个例子   911 和 9112016652 相比 后者就无法被拨通,因为 911 会先被拨通。

如果都可拨通 输出 YES 不然输出 NO

这道题意思很明确,给你 n 个字符串,每个字符串都不能是另外一个的前缀,这里我们只需要每个字符串结尾的时候 对其做一个标记,之后 对于每个新的字符串,我们遍历 从0 --- n-2位,如果发现阶数标记,那么就不能全部拨同,否则就可以。

稍微改动一下 find 和 insert 函数就可以了。

以下 为 AC 代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

const int maxn = 1e5+5;
int tree[maxn][30];
int flag[maxn];
int tot;

void _insert(char *str)
{
    int rt=0;
    int len = strlen(str);
    for(int i=0; i<len; i++)
    {
        int id = str[i] - '0';
        if(!tree[rt][id])
            tree[rt][id]=++tot;
        rt = tree[rt][id];
    }
    flag[rt] = 1;
}
bool _find(char *str)
{
    int rt=0;
    int len = strlen(str);
    for(int i=0; i<len-1; i++)
    {
        int id = str[i] - '0';
        rt = tree[rt][id];
        if(flag[rt])
            return false;
    }
    return true;
}
char ss[maxn][30];
int main()
{
    int n,t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        memset(flag,0,sizeof(flag));
        memset(tree,0,sizeof(tree));
        tot=0;
        for(int i=0;i<n;i++)
        {
            scanf("%s",ss[i]);
            _insert(ss[i]);
        }
        int cnt=1;
        for(int i=0;i<n;i++)
        {
            if(!_find(ss[i]))
            {
                cnt=0;
                break;
            }
        }
        if(cnt)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40924940/article/details/84072945
今日推荐