1. 程式人生 > >POJ 3630:Phone List(字典樹入門)

POJ 3630:Phone List(字典樹入門)

題目意思:

如果撥打的電話號碼的字首是一個完整的電話號碼,則這個電話就不能撥通,判斷給出的電話列表是否全部能撥通。

這個題目只用再建立字典樹的過程中做判斷就行了,沒必要建完之後再去查詢,我們可以在節點設定count統計某個

節點所代表的單詞當前稱為別人字首的次數。再用個bool變數記錄當前節點所代表的一串字元是不是一個完整的電話

號碼,當一個字串是完整的電話號碼,且被已經加入的串當作字首兩次,這列電話號碼就不能全部撥通。

坑點:

1.不能是用動態連結串列,malloc動態分配記憶體提交會超時,這個題目得用靜態連結串列。

2.靜態連結串列陣列開到一兩萬過不去,儘量開大點,我直接開10萬過了。

AC程式碼:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

using namespace std;

const int maxn = 10;   
char telNum[10002][14];
struct TrieNode
{
    bool isCompleteTel;
    int ccount;
    struct TrieNode *son[maxn];
}node[100000];
int num;
TrieNode* createNode()
{
   TrieNode *p = &node[num++];
   for(int i = 0; i < maxn; i++)
   {
       p->son[i] = NULL;
   }
   return p;
}
///邊插入Telphone邊判斷。不用建玩樹後再去一個個判斷。
bool insertTel(TrieNode *root,char tel[])
{
    TrieNode *p;
    p = root;
    int i = 0;
    char ch = tel[i];
    while(ch != '\0')
    {
        if(p->son[ch-'0'] == NULL)
        {

            p->son[ch-'0'] = createNode();
            p = p->son[ch-'0'];
            p->isCompleteTel = false;
            p->ccount = 1;
        }
        else
        {
            p->son[ch-'0']->ccount++;
            p = p->son[ch-'0'];
            if(p->ccount>1 && p->isCompleteTel==true)  ///如果有一串完整電話號碼已經到過這裡了。就不能撥打成功。
                return false;
        }
        ch = tel[++i];
    }
    p->isCompleteTel = true;
    if(p->ccount>1 && p->isCompleteTel==true)  ///曾經有電話號碼的字首到達過這個電話號碼的結尾了,也不行。
        return false;
    return true;
}
int main()
{
    int t,n;
    scanf("%d",&t);
    while(t--)
    {
        num = 0;
        scanf("%d",&n);
        bool OK = true;
        TrieNode *root = createNode();
        for(int i = 0; i < n; i++)
        {
            scanf("%s",telNum[i]);
            if(OK)
            {
                OK = insertTel(root,telNum[i]);
            }
        }
        if(OK)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}