题目大意是给定t组数据,每组中有n个数字构成的字符串电话号码,要求对每一组数据判断是否存在一个电话号码为另一个的前缀,如果有,则这一组数据不合要求,输出”NO”,若是没有,就是”YES”。
一眼就看出来这道题是一个裸的trie树问题,需要利用trie树这种结构判断是否存在前缀即可。
用trie树先记录每个电话号码,并将它们最末一位存下来,之后遍历所有电话号码的最末一位,如果某一个有子结点,就说明它所对应的电话号码为另一个的前缀。若均没有,则不存在一个电话号码为另一个的前缀。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=100009;
const int inf = 0x3f3f3f3f;
int n;
int tree[N][10],tot;
bool p[N];
int trie(char w[])
{
int loc=0;//0号结点是虚拟的根结点
for (int i=0;w[i];i++)//把号码的每一位都在树上走一遍
{
int x=tree[loc][w[i]-'0'];
if (x==-1)//如果下一位数字的位置还未出现过,新建一个结点并编号
tree[loc][w[i]-'0']=++tot;
loc=tree[loc][w[i]-'0'];//继续走下一位数字
}
return loc;//返回最末一位数字
}
int main()
{
int c;
for (scanf ("%d",&c);c--;)
{
memset (tree,-1,sizeof(tree));
memset (p,false,sizeof(p));
tot=0;
scanf ("%d",&n);
for (int i=1;i<=n;i++)
{
char s[21];
scanf ("%s",s);
p[trie(s)]=true;//将号码最后一个数字编号记录下
}
bool k=false;
for (int i=1;i<=tot;i++)
{
if (p[i]==true)//查询每个电话号码的最后一位
{
for (int j=0;j<=9;j++)
if (tree[i][j]!=-1)//如果发现某个电话号码的最后一位有子结点,则存在前缀
{
k=true;
break;
}
}
}
if(k)
puts("NO");
else
puts("YES");
}
return 0;
}