字典树就是在以空节点为根的基础上建立树形结构。节点可以是大小写字母或数字,每个节点都建立许多分支,同时在节点里可以加上标记或计数变量,可根据题目做调整。
由于这个题目可能后台数据过大,所以要每次得出结果后释放内存。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define Max 10 //Max should be 10 because of next array
bool Flag; // Flag is used as a tag
typedef struct trie
{
int cou;
trie *next[Max];
} node;
#define Size sizeof(trie)
trie *New_node() //build new node
{
trie *p;
p=(trie*)malloc(Size);
p->cou=0; //initialized to 0
for(int i=0; i<Max; i++)
p->next[i]=NULL;
return p;
}
void inser(trie *root,char *word)
{
int i=0,b,l;
l=strlen(word);
trie *p=root;
while(word[i])
{
b=word[i]-'0';
if(!p->next[b])
{
p->next[b]=New_node(); //if the number node is null ,build the node
if(i<l-1) // not be the last one ,remember to 1
p->next[b]->cou=1;
else
p->next[b]->cou=2; //if it is the last ,remember to 2
if(p->cou==2) // if the current node's cou is 2,Flag remember to 1
{
p->cou=1; //123 1234
Flag=1;
}
}
else
{
if(i==l-1) //if the number node isn't null and is the last ,Flag remembers to 1
{
Flag=1; //1234 123
}
}
i++;
p=p->next[b];
}
}
void del(trie *root) //释放内存
{
if(root) //根节点非空
{
for(int i=0;i<Max;i++)
del(root->next[i]);//递归释放根节点的子节点
free(root); //释放根节点
}
}
int main()
{
int t,n;
char a[15];
scanf("%d",&t);
while(t--)
{
Flag=0;
trie *Root=New_node(); //build root node
scanf("%d",&n);
for(int j=0; j<n; j++)
{
scanf("%s",&a);
inser(Root,a);
}
if(Flag==0)
printf("YES\n");
else
printf("NO\n");
del(Root);
}
return 0;
}
</span></p>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define Max 10 //Max should be 10 because of next array
bool Flag; // Flag is used as a tag
typedef struct trie
{
int cou;
trie *next[Max];
} node;
#define Size sizeof(trie)
trie *New_node() //build new node
{
trie *p;
p=(trie*)malloc(Size);
p->cou=0; //initialized to 0
for(int i=0; i<Max; i++)
p->next[i]=NULL;
return p;
}
void inser(trie *root,char *word)
{
int i=0,b,l;
l=strlen(word);
trie *p=root;
while(word[i])
{
b=word[i]-'0';
if(!p->next[b])
{
p->next[b]=New_node(); //if the number node is null ,build the node
if(i<l-1) // not be the last one ,remember to 1
p->next[b]->cou=1;
else
p->next[b]->cou=2; //if it is the last ,remember to 2
if(p->cou==2) // if the current node's cou is 2,Flag remember to 1
{
p->cou=1; //123 1234
Flag=1;
}
}
else
{
if(i==l-1) //if the number node isn't null and is the last ,Flag remembers to 1
{
Flag=1; //1234 123
}
}
i++;
p=p->next[b];
}
}
void del(trie *root) //释放内存
{
if(root) //根节点非空
{
for(int i=0;i<Max;i++)
del(root->next[i]);//递归释放根节点的子节点
free(root); //释放根节点
}
}
int main()
{
int t,n;
char a[15];
scanf("%d",&t);
while(t--)
{
Flag=0;
trie *Root=New_node(); //build root node
scanf("%d",&n);
for(int j=0; j<n; j++)
{
scanf("%s",&a);
inser(Root,a);
}
if(Flag==0)
printf("YES\n");
else
printf("NO\n");
del(Root);
}
return 0;
}
</span></p>
在博客里看到了有大牛写的模板,感觉实在太完美了,附在下边。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define Max 10
bool Flag;
typedef struct trie
{
int cou;
trie *next[Max];
} node;
#define Size sizeof(trie)
trie *New_node()
{
trie *p;
p=(trie*)malloc(Size);
p->cou=1;
for(int i=0; i<Max; i++)
p->next[i]=NULL;
return p;
}
void creattrie(trie *root,char *str)
{
int len=strlen(str);
trie *p=root;
for(int i=0;i<len;i++)
{
int id=str[i]-'0';
if(!p->next[id]) //如果该数字节点为空节点,让p->next[id]指向新建节点
{
p->next[id]==New_node();
}
else
{
p->next[id]->cou++; //如果该数字节点不空,让该节点的cou自加
}
p=p->next[id]; //指针后移
}
p->cou=-1; //将该字符串的最后一个节点的cou置为-1作标志
}
bool findtrie(trie *root,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) //如果该数字节点为空表示没有该节点
return false;
if(p->cou==-1) //如果该数字节点的cou为-1,则表示字典树字符集(123)中有此字符串(1234)的前缀
return true;
}
return true; //如果此字符串遍历完后还没有返回值,则说明此字符串(1234)是字典树中字符集(123)的前缀
}
void del(trie *root) //释放内存
{
if(root) //根节点非空
{
for(int i=0;i<Max;i++)
del(root->next[i]);//递归释放根节点的子节点
free(root); //释放根节点
}
}
int main()
{
int t,n;
char a[15];
scanf("%d",&t);
while(t--)
{
Flag=0;
trie *Root=New_node(); //build root node
scanf("%d",&n);
for(int j=0; j<n; j++)
{
scanf("%s",&a);
if(findtrie(Root,a)) //如果找到a的前缀或a为前缀,Flag=1
Flag=1;
if(Flag) //如果Flag已经是1了,就加快程序节奏
continue;
creattrie(Root,a); //如果没有找到前缀,就继续构建字典树
}
if(!Flag)
printf("YES\n");
else
printf("NO\n");
del(Root);
}
return 0;
}
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define Max 10
bool Flag;
typedef struct trie
{
int cou;
trie *next[Max];
} node;
#define Size sizeof(trie)
trie *New_node()
{
trie *p;
p=(trie*)malloc(Size);
p->cou=1;
for(int i=0; i<Max; i++)
p->next[i]=NULL;
return p;
}
void creattrie(trie *root,char *str)
{
int len=strlen(str);
trie *p=root;
for(int i=0;i<len;i++)
{
int id=str[i]-'0';
if(!p->next[id]) //如果该数字节点为空节点,让p->next[id]指向新建节点
{
p->next[id]==New_node();
}
else
{
p->next[id]->cou++; //如果该数字节点不空,让该节点的cou自加
}
p=p->next[id]; //指针后移
}
p->cou=-1; //将该字符串的最后一个节点的cou置为-1作标志
}
bool findtrie(trie *root,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) //如果该数字节点为空表示没有该节点
return false;
if(p->cou==-1) //如果该数字节点的cou为-1,则表示字典树字符集(123)中有此字符串(1234)的前缀
return true;
}
return true; //如果此字符串遍历完后还没有返回值,则说明此字符串(1234)是字典树中字符集(123)的前缀
}
void del(trie *root) //释放内存
{
if(root) //根节点非空
{
for(int i=0;i<Max;i++)
del(root->next[i]);//递归释放根节点的子节点
free(root); //释放根节点
}
}
int main()
{
int t,n;
char a[15];
scanf("%d",&t);
while(t--)
{
Flag=0;
trie *Root=New_node(); //build root node
scanf("%d",&n);
for(int j=0; j<n; j++)
{
scanf("%s",&a);
if(findtrie(Root,a)) //如果找到a的前缀或a为前缀,Flag=1
Flag=1;
if(Flag) //如果Flag已经是1了,就加快程序节奏
continue;
creattrie(Root,a); //如果没有找到前缀,就继续构建字典树
}
if(!Flag)
printf("YES\n");
else
printf("NO\n");
del(Root);
}
return 0;
}