poj 3630 Phone List

題意:一些電話號碼,問其中是否有某些號碼是其他號碼的前綴

思路:Trie樹,若某個字母出現過不止一次且它是某個電話號碼的最後一個字母,則輸出 NO

由於題目數據較大,若每次插入的時候都用new 會超時,所以先定義一個數組,然後每次直接取地址,不需要用new來獲得

#include<iostream>
using namespace std;
char num[10010][11];
int len[10010];
int n;
struct node
{
	node *child[10];
	bool terminal;//true表示是結尾字符
	int num;
}*root,tree[100000]; 
int ans;
void trie()
{
	root = new node;
	for(int i = 0;i < 10;i++)
		root->child[i] = NULL;
}
void insert(int k)
{
	node *r = root,*p;
	for(int i = 0;i < len[k];i++)
	{
		if(r->child[num[k][i]-'0'] == NULL)
		{
			r->child[num[k][i]-'0'] = &tree[ans];//直接new會超時 所以先建立一個buffer 即建立一個數組 然後取取他的地址
			tree[ans].terminal = false;
			tree[ans].num = 0;
			for(int j = 0;j < 10;j++)
				tree[ans].child[j] = NULL;
			ans++;
		}
		r = r->child[num[k][i]-'0'];
		r->num++;
	}
	r->terminal = true;
}
bool find(int k)
{
	node *r = root,*p;
	for(int i = 0;i < len[k];i++)
	{
		p = r->child[num[k][i]-'0'];
		if(p->num > 1&&p->terminal)
			return false;
		r = r->child[num[k][i]-'0'];
	}
	return true;
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		int i;
		ans = 0;
		trie();
		for(i = 0;i < n;i++)
		{
			scanf("%s",num[i]);
			len[i] = strlen(num[i]);
			insert(i);
		}
		for(i = 0;i < n;i++)
		{
			if(!find(i))
				break;
		}
		if(i < n)
			printf("NO\n");
		else
			printf("YES\n");
	}
	return 0;
}


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