#include <iostream>
using namespace std;
//定义一个结构体
typedef struct Trie{
int v;//表示这一层的元素个数,如果这一层为-1.表示没有元素
Trie *next[10];//下一个节点有10个
}Trie;
Trie *root;//声明一个根???????????????
void createTrie(char *str)
{
int len = strlen(str);
Trie *p = root, *q;//p表示游标
for(int i=0; i<len; ++i)
{
int id = str[i]-'0';//标号
//如果说下一个节点为空,那么新建一个trie树,接上去
if(p->next[id] == NULL)
{
//生成一个trie树
q = (Trie *)malloc(sizeof(Trie));
q->v = 1;
//把新树的其它节点都做成空
for(int j=0; j<10; ++j)
q->next[j] = NULL;
//接上数
p->next[id] = q;
//移动游标
p = p->next[id];
}
//如果说这个节点不是空,比如说119和110.当插入119以后,119都是1.
//当插入110的时候,v的值变为2.但是9和0都是1
else
{
p->next[id]->v++;
p = p->next[id];//移动游标
}
}
//最后一个节点定义为空。当插入113的时候,113都插入啦。让后3的下一个是-1
p->v = -1;
}
//这个find函数还有一点问题。
int findTrie(char *str)
{
int len = strlen(str);
Trie *p = root;//先把游标指向根节点
//一层一层的插入
for(int i=0; i<len; ++i)
{
int id = str[i]-'0';
p = p->next[id];
//如果说这一层是空,
if(p == NULL)
return 0;
if(p->v == -1)
return -1;
}
return -1;
}
int deal(Trie* T)
{//这是把T清空,一开始没加这个,结果MLE.
int i;
if(T==NULL)
return 0;
for(i=0;i<10;i++)
{
if(T->next[i]!=NULL)
deal(T->next[i]);
}
free(T);
return 0;
}
#define MAX 10005
//#define MAX 10
class Point
{
public:
char name[10];
int length;
};
Point point[MAX];
int compare(const void *a,const void *b)
{
return ((Point*)b)->length-((Point*)a)->length;
}
int is(char *str)
{
int len = strlen(str);
Trie *p = root, *q;//p表示游标
for(int i=0; i<len; ++i)
{
int id = str[i]-'0';//标号
//如果说下一个节点值为空,表示不是前缀
if(p->next[id] == NULL)
{
return 1;//返回1表示不是前缀,可以继续插入
}
//如果说这个节点不是空,比如说119和110.当插入119以后,119都是1.
//当插入110的时候,v的值变为2.但是9和0都是1
//那么移动游标
else
{
p = p->next[id];//移动游标
}
}
return 0;//比如说插入11935,让后插入119,插入以后发现,所有的点都有啦,表示不可以在插入啦
}
int main()
{
//freopen("in.txt", "r", stdin);
int nCases, nNum;
int i;
scanf("%d", &nCases);
while(nCases--)
{
root = (Trie *) malloc (sizeof(Trie));//新建一个trie树。
//把数初始化
for(i=0; i<10; ++i)
root->next[i] = NULL;
//输入一个数字
scanf("%d", &nNum);
for(i=0; i<nNum; ++i)
{
scanf("%s", point[i].name);
point[i].length=strlen(point[i].name);
}
qsort(point,nNum,sizeof(Point),compare);
//开始处理
int flag=1;//表示可以
for(i=0;i<nNum;i++)
{
//如果说不是前缀,就插入
if(is(point[i].name))
{
createTrie(point[i].name);
}
//如果说是前缀,返回0
else
{
flag=0;
break;
}
}
if(flag==0)
printf("NO\n");
else
printf("YES\n");
//清除动态内存
deal(root);
}
return 0;
}
/*
1 例如911,最后一个1的exist的值是“f”(就是法文的符号)。
2 如果这个点没有元素就是0x00000000如果有元素就是0x2806e0;
3 当比赛的时候,最好看原版的东西。因为都没有经过修改
*/
hdoj 1671(trie树)(要清除动态内存,要不然的话就会mtl)(还有很重要的东西写在代码的最后注释当中)
最新推荐文章于 2022-07-01 19:28:43 发布