1. 程式人生 > >POJ 3630 靜態字典樹

POJ 3630 靜態字典樹

題意:給你一些電話號碼,問你是否有一個電話號碼是其他電話號碼字首

比如,911 和911584這兩個號碼,911是911584的字首

解題思路:經過pork大神的指導,估計時間如下,一共有10000個電話號碼插入,每個號碼最長10位,如果每次插入最差就是開闢10個新的節點,那就是10000*10*10個,一百W,如果有new開闢的話,時間耗費嚴重,超時是必然的,那麼用靜態陣列,提前開闢100W個,用的時候就把它提出來。

檢測的時候先按長度排序,舉個discuss的反例

2
2
1
12
2
12
1
NO
NO
必須先保證長度小的先被插入字典樹裡面,這樣長度長的才能檢測出來
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
struct Dictree
{
	bool in;
	struct Dictree *next[10];
}node[1000000];
Dictree root;
int cmp(const void *a,const void *b)
{
	char *p1,*p2;
	p1=(char *)a;
	p2=(char *)b;
	return strlen(p1)-strlen(p2);
}
int tot;
char s[10005][12];
bool reflect;
void create_tree();
void insert(char *);
int main()
{
	int cas,n,i;
	for(scanf("%d",&cas);cas;cas--)
	{
		reflect=false;
		create_tree();
		scanf("%d",&n);
		for(i=0;i<n;i++)
			scanf("%s",s[i]);
		qsort(s,n,sizeof(s[0]),cmp);
		for(i=0;i<n;i++) 
			if(!reflect) insert(s[i]);
		if(reflect) printf("NO\n");
		else printf("YES\n");
	}
	return 0;
}
void create_tree()
{
	root.in=false;
	tot=0;
	memset(root.next,NULL,sizeof(root.next));
}
void insert(char *s)
{
	int i;
	struct Dictree *p;
	p=&root;
	for(i=0;s[i];i++)
	{
		if(p->next[s[i]-'0']==NULL)
		{
			node[tot].in=false;
			memset(node[tot].next,NULL,sizeof(node[tot].next));
			p->next[s[i]-'0']=&node[tot++];
		}
		p=p->next[s[i]-'0'];
		if(p->in) reflect=true;
	}
	p->in=true;
}