由于存在多组数据,所以每组数据结束后要清空树。
还是很喜欢在结构体里对节点进行初始化,方便快捷。
判断一组数是否出现某数为另一个数的前缀,只需在中间每一步分别判断该数是否已经是前面数的前缀和该数是否是后面数的前缀。在字典树中判断这种条件再简单不过,用exist代表是否出现以该节点结尾的单词,用sum代表以该节点结尾为前缀的单词数还有多少个,中间加判断条件即可。
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
typedef long long LL;
const int N = 15;
const int INF = 1e8;
struct Trie
{
int sum;
bool exist;
Trie *next[10];
Trie()
{
exist = 0;
sum = 0;
for(int i = 0; i < 10; i ++)
next[i] = 0;
}
}*root;
bool inserttrie(Trie *p, char *str)
{
int k = 0;
while(str[k] != '\0')
{
int id = str[k] - '0';
if(p -> next[id] == 0) p -> next[id] = new Trie;
p = p -> next[id];
if(p -> exist) return 0;
p -> sum ++;
k ++;
}
p -> exist = 1;
if(p -> sum > 1) return 0;
return 1;
}
/*int findtrie(char *str)
{
int k = 0;
Trie *p = &root;
while(str[k] != '\0' && p -> next[str[k] - 'a']) p = p -> next[str[k ++] - 'a'];
return str[k] == '\0' ? p -> sum : 0;
}*/
void Free(Trie *p)
{
for(int i = 0; i < 10; i ++)
if(p -> next[i]) Free(p -> next[i]);
if(p) delete p;
}
int main()
{
// freopen("in.txt", "r", stdin);
int t, n;
char s[N];
scanf("%d", &t);
while(t --)
{
root = new Trie;
int flag = 1;
scanf("%d", &n);
while(n --)
{
cin >> s;
if(!inserttrie(root, s))
{
flag = 0;
}
}
if(flag) printf("YES\n");
else printf("NO\n");
Free(root);
}
return 0;
}