题意:一些电话号码,问其中是否有某些号码是其他号码的前缀
思路: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;
}