字典树(hihocoder1014)
字典树又称前缀树或者trie树,一种有序数据结构,用于保存关联数组,键通常是字符串。
Trie的核心思想是空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。
它的插入和查询时间复杂度都为 O(k) ,其中 k 为 key 的长度,与 Trie 中保存了多少个元素无关。;Trie 的缺点是空间消耗很高。
1.构建树:
构建字典树的单个节点需要有键值,子节点指针必不可少。
struct node{
char key;
node* next[num];
};
num的值控制在比键值的类别数大就可以;
根节点没有任何键值。
对于其他的要求可以适当的在结构体中添加,注意要结合题意和树形结构的优点。
2.对树的操作:
对树的操作无非插入和查询,删除操作:
插入和查询都可以沿着树依次搜索到目标节点,再操作。
删除操作可以采用递归的形式。
3.hihocoder1014
这是一个字典树的模板题,我们这个只需要按照步骤来构建树,再查询到前缀字符串的最后一个节点,就是正确的答案。
#include <bits/stdc++.h>
using namespace std;
struct node
{
char c; //键值
int L; //储存以当前结点为根节点的子树的叶子数。
node* next[26];
node()
{
memset(next,NULL,sizeof(next));
L=0;
}
node(char c):c(c){
memset(next,NULL,sizeof(next));
L=0;
}
} root; //根节点
const int maxn =100000+5;
char str[maxn];
void new_triTree(node* t,int len) //对树进行插入操作
{
t->L++;
if(len==strlen(str))
return;
for(int i=0; i<26; i++)
{
if(t->next[i]==NULL) //不存在该节点,创建一个新的子节点
{
t->next[i] = new node(str[len]);
new_triTree(t->next[i],len+1);
break;
}
if(t->next[i]->c ==str[len] ) //存在该节点
{
new_triTree(t->next[i],len+1 );
break;
}
}
return;
}
void print_fun(node* t,int len){ //查询操作
//if(t==NULL) return;
if(len==strlen(str)){
printf("%d\n",t->L);
return ;
}
for(int i=0; i<26; i++)
{
if(t->next[i]==NULL) {
printf("0\n");
break;
}
if(str[len]==t->next[i]->c){
print_fun(t->next[i],len+1);
break;
}
}
return ;
}
int main()
{
int n;
while(scanf("%d",&n)==1)
{
for(int i=0; i<n; i++)
{
scanf("%s",str);
new_triTree(&root,0);
}
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%s",str);
print_fun(&root,0);
}
}
return 0;
}