Phone List(trie树)

原题来自:POJ 3630

给定 n个长度不超过 10的数字串,问其中是否存在两个数字串s,t,使得 s是 t的前缀,多组数据。

输入格式
第一行一个整数t,表示数据组数。

对于每组数据,第一行一个数n,接下来n行输入n个数字串。

输出格式
对于每组数据,若存在两个数字串s,t,使得s是t的前缀,则输出 NO ,否则输出 YES 。

请注意此处结果与输出的对应关系!

样例
样例输入
2
3
911
97625999
91125426
5
113
12340
123440
12345
98346
样例输出
NO
YES
思路
使用Trie树。将每一个号码插入到树中,如发现该号码前缀已经出现在树中,或者该号码成为其他号码的前缀的话,即返回“NO”。如果全部号码输入后都没出现过,则输出“YES”。
``

include <string.h>

include <stdio.h>

include

include

using namespace std;
const int maxn=1e5+10;
int tre[maxn*2][11],sz;
struct node
{
int len;
char a[11];
}map[maxn];
int n,m;
bool cmp(node x,node y)
{
return x.len>y.len;
}//必要的一步,按长度从大到小排序
bool solve (int t)
{
int len=map[t].len;
int now=0;
for (int i=0;i<len;++i)
{
int tem=map[t].a[i]-'0';//字符转成数字,入树
if (i==len-1&&tre[now][tem])
return 0;
if (!tre[now][tem])
tre[now][tem]=++sz;//

	now=tre[now][tem];//本层的节点作为下一层 
}
return 1;

}
int main()
{
int i,j,T;
scanf("%d",&T);
while(T--)
{
sz=0;
memset(tre,0,sizeof(tre));
scanf("%d",&n);
for (i=0;i<n;++i)
{
scanf("%s",map[i].a);
map[i].len=strlen(map[i].a);
}
sort(map,map+n,cmp);

	int flag=0;
	for (i=0;i<n;++i)
	{
		if (!solve(i))
		{
			flag=1;
			break;
		}
	}
	if (flag)
	printf("NO\n");
	else
	printf("YES\n");
}

return 0;

}

`

posted @ 2020-11-09 20:56  索饮  阅读(148)  评论(0编辑  收藏  举报