Trie树介绍与动态构造->HDU1251

来源:互联网 发布:金融随机分析 知乎 编辑:程序博客网 时间:2024/05/29 07:40

Trie树介绍:

Trie树,称为单词前缀树,字典树,是一种用于快速检索的多叉树结构

核心思想:

空间换时间,利用字符串的公共前缀来最大限度地减少无所谓的字符串比较,从而降低时间复杂度。

基本性质:

1.根节点不包含字符,除根节点外的每条边对应一个字符
2.从根节点到某一个节点,将边上的字符连起来,会得到该节点对应的前缀
3.每个节点对应的前缀都不相同


Trie树的编程实现

1.Trie树节点的定义:

struct Trie{    int count;    Trie *childs[26];    bool last ;    Trie()    {        count=0;        int i;        for(i=0;i<26;i++)        childs[i]=NULL;        last = false ;    }};Trie *root=new Trie;

说明:

childs[i]:表示当前节点基于第i个字符的边,如果不存在,则其值为NULL;否则指向经过这个字符转移的下一个节点

count:使用到该节点的前缀的单词数量

Trie():构造函数,将节点中的count的数量和childs数组初始化

Trie *root = new Trie :使用new动态分配一个存储空间,并让root指向该空间

2.Trie树的插入:

void insert(char *str){    int i,m;    current=root;    for(i=0;i<strlen(str);i++)    {        m=str[i]-'a';        if(current->childs[m]!=NULL)        {            current=current->childs[m];            ++(current->count);        }        else        {            newnode=new Trie;            ++(newnode->count);            current->childs[m]=newnode;            current=newnode;        }    }    current->last = true ;}

说明:

假设存在字符串str,Trie树的根结点为root。i=0,current=root。

1)取str[i],判断current->childs[str[i]-‘a’]是否为空,

若为空:
则建立结点newnode,并将current->childs[str[i]-‘a’]指向newnode,然后current指向newnode;

若不为空:
则current=current->childs[str[i]-‘a’];

2)i++,继续取str[i],循环1)中的操作,直到遇到结束符’\0’,此时将当前结点current中的 last置为true。

3.Trie树的查询:
查询某个前缀的使用次数:

int search(char *str){    int i,m;    current=root;    for(i=0;i<strlen(str);i++)    {        m=str[i]-'a';        if(current->childs[m]==NULL)        return 0;        current=current->childs[m];    }    return current->count;}

说明:

假设要查找的字符串为str,Trie树的根结点为root,i=0,current=root

1)取str[i],判断判断current->childs[str[i]-‘a’]
是否为空,若为空,则返回0;
若不为空,则继续取字符。

2)重复1)中的操作直到遇到结束符’\0’,若当前结点current不为空,则返回current->count。

查询某个单词是否存在:

int search(char *str){    int i,m;    if(!childs[m]) return false;    current=root;    for(i=0;i<strlen(str);i++)    {        m=str[i]-'a';        if(current->childs[m]==NULL)            return 0;        current=current->childs[m];    }    if(current -> last)        return true;    return false;}

4.Trie的删除
注意:动态Trie树一定要释放内存!

void DelTrie(Trie *t){    if(!t) return ;    for(int i = 0 ; i < maxn ; i++)    {        if(t -> childs[i])            DelTrie(t -> childs[i]) ;    }    delete t ;}

说明:

从根节点开始不断进入当前节点的子节点,直到走到叶子节点,并释放当前空间


HDU1251

题意:

先给出几个单词,之后给出几个前缀,查询那些单词中这些前缀分别出现过多少次

题解:

简单的Trie树的应用

代码:

#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>using namespace std;struct node{    int count;    node *childs[26];    node()    {        count=0;        int i;        for(i=0;i<26;i++)        childs[i]=NULL;    }};node *root=new node;node *current,*newnode;void insert(char *str){    int i,m;    current=root;    for(i=0;i<strlen(str);i++)    {        m=str[i]-'a';        if(current->childs[m]!=NULL)        {            current=current->childs[m];            ++(current->count);        }        else        {            newnode=new node;            ++(newnode->count);            current->childs[m]=newnode;            current=newnode;        }    }}int search(char *str){    int i,m;    current=root;    for(i=0;i<strlen(str);i++)    {        m=str[i]-'a';        if(current->childs[m]==NULL)        return 0;        current=current->childs[m];    }    return current->count;}int main(){    char str[20];    while(gets(str),strcmp(str,""))    insert(str);    while(gets(str)!=NULL)    printf("%d\n",search(str));    return 0;}
0 0
原创粉丝点击