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;
}
`