重新码一遍字典树会对字典树有着更深的印象,原来是直接动态开辟的空间,觉得这样的方法好麻烦,自己借鉴代码写的利用已知存储空间来求字典树。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
using namespace std;
const int max_child=200000;
const int char_set=26;
const char base='0'; //注意这里是基数 是0 抄代码时直接看成是a了 导致错误。
const int input=20000;
char a[input][20];
struct Tire{
int tot,root,child[max_child][char_set];
int flag[max_child];
Tire(){
tot=1;
root=1;
memset(child[1],0,sizeof(child[1]));
flag[0]=0;
}
void reset(int n){ //直接reset恢复原状。
root=1;
tot=1;
memset(child[1],0,sizeof(child[1]));
memset(flag,0,sizeof(int)*n*10);
}
void insert(char *str){ //查询
int *cur=&root;
for (char *p=str;*p;p++){
cur=&child[*cur][*p-base];
if (*cur==0){
*cur=++tot;
memset(child[*cur],0,sizeof(child[*cur]));
}
flag[*cur]++; //这里一定要是*cur 因为重复计数的也要将flag中的值加1 例如 aaa和aaaaa要依次相加
//printf("%d %d %d\n",*cur,tot,flag[*cur]); //这是输出测试结果的代码。
}
}
int query(char *str){ //询问。
int *cur=&root;
for (char *p=str;*p;p++){
cur=&child[*cur][*p-base];
}
//printf("%d flag[*cur]=%d\n",*cur,flag[*cur]);
if(flag[*cur]!=1)return 1; //存在
else return 0;
}
} tree;
int main()
{
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
tree.reset(n);
for(int i=1;i<=n;i++){
scanf("%s",a[i]);
tree.insert(a[i]);
}
int flag=0;
for(int i=1;i<=n;i++){
flag=tree.query(a[i]);
//printf("roud=%d %d\n",i,flag);
if(flag==1)break;
}
if(flag==1)printf("NO\n");
else printf("YES\n");
}
return 0;
}