poj3630 Phone List與Trie

題目:

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有以下兩種情況:

  1. trie中的某個字符串是當前字符串的前綴(包括與當前字符串相同)。等價於在插入當前字符串時,會遇到(isEnd==true)的標記。
  2. 當前字符串是trie中的某個字符串的前綴。等價於當前字符串插入完畢後,最後一個結點存在非空的兒子。
若非以上兩點,當前字符串可以合法插入trie。

ps:
  1. 據說此題若動態分配結點內存在poj上會超時,我在openjudge上並沒有遇到這種情況。
  2. 只要有一個條目不能合法添加至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;
}

發佈了50 篇原創文章 · 獲贊 16 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章