1. 程式人生 > >POJ 3630

POJ 3630

這道題目依舊是 字典樹題目

大意:

目前有 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;
}