題目:
9:電話號碼
- 總時間限制:
- 1000ms
- 內存限制:
- 65536kB
- 描述
-
給你一些電話號碼,請判斷它們是否是一致的,即是否有某個電話是另一個電話的前綴。比如:
Emergency 911
Alice 97 625 999
Bob 91 12 54 26
在這個例子中,我們不可能撥通Bob的電話,因爲Emergency的電話是它的前綴,當撥打Bob的電話時會先接通Emergency,所以這些電話號碼不是一致的。 - 輸入
- 第一行是一個整數t,1 ≤ t ≤ 40,表示測試數據的數目。
每個測試樣例的第一行是一個整數n,1 ≤ n ≤ 10000,其後n行每行是一個不超過10位的電話號碼。 - 輸出
- 對於每個測試數據,如果是一致的輸出“YES”,如果不是輸出“NO”。
- 樣例輸入
-
2 3 911 97625999 91125426 5 113 12340 123440 12345 98346
- 樣例輸出
-
NO YES
建立一個trie,邊插字符串入邊判斷。電話本inconsistent有以下兩種情況:
- trie中的某個字符串是當前字符串的前綴(包括與當前字符串相同)。等價於在插入當前字符串時,會遇到(isEnd==true)的標記。
- 當前字符串是trie中的某個字符串的前綴。等價於當前字符串插入完畢後,最後一個結點存在非空的兒子。
- 據說此題若動態分配結點內存在poj上會超時,我在openjudge上並沒有遇到這種情況。
- 只要有一個條目不能合法添加至trie,那麼phone list inconsistent。但逐條輸入entry的循環卻不能在此break,還是要把這組數據遍歷完畢纔可以;否則下一組數據取到的第一個條目就不對(因爲在上一組數據進行到一半時break了)。我就在這裏wa了很久...
//trie
//判斷trie中新加入的字符串是不是其他字符串的前綴,以及其他字符串是不是它的前綴
#include <iostream>
using namespace std;
#include <string.h>
#define MAXN 15
#define MAXCHILD 10
#define DYNAMICALLOC
typedef struct _trie
{
bool isEnd;
struct _trie *nextchar[MAXCHILD];
} trie;
bool insert_and_judge_if_valid(char entry[], trie *root)
{
int char_len=strlen(entry);
int i, overlap_node=0, j;
trie *current=root;
char temp;
for (i=0; i<char_len; ++i)
{
temp=entry[i]-'0';
if(current->nextchar[temp] == NULL) //下一個字符是新的路徑點
{
#ifdef DYNAMICALLOC
current->nextchar[temp]=new trie;
current->nextchar[temp]->isEnd=false;
for (j=0; j<MAXCHILD; ++j)
{
current->nextchar[temp]->nextchar[j]=NULL;
}
#endif
}
if(current->nextchar[temp]->isEnd) //某個字符串是當前字符串的前綴,invalid
return false;
current=current->nextchar[temp];
}
//最後一個結點設置結束標誌位
current->isEnd=true;
//若最後一個結點有任何一個非空的兒子,說明當前字符串是某個字符串的前綴
for (i=0; i<MAXCHILD; ++i)
{
if (current->nextchar[i] != NULL)
{
return false;
}
}
//以上兩個失敗條件都不滿足,則可以插入phone list
return true;
}
#ifdef DYNAMICALLOC
void destroy_trie(trie *root) //後續遍歷二叉樹的模板銷燬trie
{
int i;
if(root!=NULL)
{
for (i=0; i<MAXCHILD; ++i)
{
destroy_trie(root->nextchar[i]);
}
delete root;
root=NULL;
}
}
#endif
int main()
{
freopen("D:\\in.txt", "r", stdin);
freopen("D:\\out.txt", "w", stdout);
int t, n, i, j, flag;
bool isValid;
char entry_in[MAXN];
trie *root;
cin>>t;
for (i=0; i<t; ++i)
{
cin>>n;
cin.get(); //把n後面的換行符拿走
#ifdef DYNAMICALLOC
root=new trie;
root->isEnd=false;
for (j=0; j<MAXCHILD; ++j)
{
root->nextchar[j]=NULL;
}
#endif
flag=0;
for (j=0; j<n; ++j)
{
cin.getline(entry_in, MAXN, '\n');
isValid=insert_and_judge_if_valid(entry_in, root);
if (!isValid)
{
flag=1;
}
}
if (flag == 1)
{
cout<<"NO"<<endl;
}
else
cout<<"YES"<<endl;
#ifdef DYNAMICALLOC
destroy_trie(root);
#endif
}
return 0;
}