• trie树(字典树)


    核心思想:

    利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的

    举个例子

    上图是由

    • am
    • as
    • tea
    • too
    • tooth
    • two

    构成的字典树。每个节点代表的单词是从根遍历到他的路径,标黄的是当前节点存在单词

    代码实现:

    struct Trie{
        Trie *son[26];
        bool w;//记录当前节点是否是单词;
        Trie(){
            memset(son,0,sizeof(son)),w=0;
        } 
    }root;

    基本性质:

    1. 根节点不包含字符,除根节点外每一个节点都只包含一个字符。
    2. 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
    3. 每个节点的所有子节点包含的字符都不相同。

    查询和插入

    对于一个单词,我只要按照它的每个字母从根走到对应的节点,再看这个节点是否被标记为黄色就可以知道它是否出现过了。
    如果没被标记,把这个节点标记为红色,就相当于插入了这个单词,这样查找和插入就可以一起实现。

    代码实现:(这里字典树只支持大写字母)

    int  sum,word;
    void search(char s[]){//查找和插入 
        Trie *x=&root;
        for(int i=0;s[i];i++){
            if(x->son[s[i]-'A']==NULL){//判断之前是否出现过 
                x->son[s[i]-'A']=new Trie;//创建新的节点 
                sum++;//sum总结点数+1
            }
            x=x->son[s[i]-'A'];
        }
        if(!x->w)word,x->w=1;//word总单词数+1 
    }

    因为空间是动态分配的,所以用完要释放

    void node_free(Trie* x){//节点释放 
        for(int i=0;i<26;i++){
            if(x->son[i]!=NULL)node_free(x->son[i]);//先释放子节点 
        }
        delete x;
    } 
    void trie_free(){//空间释放 
        for(int i=0;i<26;i++){
            if(root.son[i]!=NULL)node_free(root.son[i]),root.son[i]=NULL;
        }
    }

     例题

    [NOI2000] 单词查找树

    代码

    #include<cstdio>
    #include<cstring>
    using namespace std;
    struct Trie{
        Trie *son[26];
        bool w;//记录当前节点是否是单词;
        Trie(){
            memset(son,0,sizeof(son)),w=0;
        } 
    }root;
    int  sum,word;
    void search(char s[]){//查找和插入 
        Trie *x=&root;
        for(int i=0;s[i];i++){
            if(x->son[s[i]-'A']==NULL){//判断之前是否出现过 
                x->son[s[i]-'A']=new Trie;//创建新的节点 
                sum++;
            }
            x=x->son[s[i]-'A'];
        }
        if(!x->w)word,x->w=1;//sum总结点数+1 
    }
    void node_free(Trie* x){//节点释放 
        for(int i=0;i<26;i++){
            if(x->son[i]!=NULL)node_free(x->son[i]);//先释放子节点 
        }
        delete x;
    } 
    void trie_free(){//空间释放 
        for(int i=0;i<26;i++){
            if(root.son[i]!=NULL)node_free(root.son[i]);
        }
    }
    char s[64];
    int main(){
        freopen("trie.in","r",stdin);
        freopen("trie.out","w",stdout);
        while(~scanf("%s",s)){
            search(s);
        }
        trie_free();
        printf("%d",sum+1);
        return 0;
    }
  • 相关阅读:
    《构建之法》第8、9、10章 读后感
    [团队项目]SCRUM项目6.0 7.0 (新)
    [团队项目]SCRUM项目5.0
    [团队项目]SCRUM项目4.0
    [团队项目] Scrum 项目 3.0 SCRUM 流程的步骤2: Spring 计划
    [操作系统]实验三 进程调度模拟程序
    [团队项目] Scrum 项目 2.0 产品BACKLOG
    复利计算的总结
    复利/单利计算程序进度0321更新
    0312 复利计算器2.0 运行与介绍
  • 原文地址:https://www.cnblogs.com/bennettz/p/7636021.html
Copyright © 2020-2023  润新知