zoukankan      html  css  js  c++  java
  • [算法]字典树

    Trie树就是字典树,其核心思想就是空间换时间。

     后缀树 suffix tree:http://www.cnblogs.com/snowberg/archive/2011/10/21/2468588.html

    字典树作用:

    1、查找单词是否出现

    2、查找单词第一次出现位置(在最后一个字母节点标记第一次出现位置)

    3、查找包含前序的单词个数(每新增一个单词进树,所经过的节点的计数器加一)

    4、将所有单词按字母次序输出


    举个简单的例子。


    给你100000个长度不超过10的单词。对于每一个单词,我们要判断他出没出现过,如果出现了,第一次出现第几个位置。
    这题当然可以用hash来,但是我要介绍的是trie树。在某些方面它的用途更大。比如说对于某一个单词,我要询问它的前缀是否出现过。这样hash就不好搞了,而用trie还是很简单。
    现在回到例子中,如果我们用最傻的方法,对于每一个单词,我们都要去查找它前面的单词中是否有它。那么这个算法的复杂度就是O(n^2)。显然对于100000的范围难以接受。现在我们换个思路想。假设我要查询的单词是abcd,那么在他前面的单词中,以b,c,d,f之类开头的我显然不必考虑。而只要找以a开头的中是否存在abcd就可以了。同样的,在以a开头中的单词中,我们只要考虑以b作为第二个字母的……这样一个树的模型就渐渐清晰了……
    假设有b,abc,abd,bcd,abcd,efg,hii这6个单词,我们构建的树就是这样的。

    对于每一个节点,从根遍历到他的过程就是一个单词,如果这个节点被标记为红色,就表示这个单词存在,否则不存在。
    那么,对于一个单词,我只要顺着他从跟走到对应的节点,再看这个节点是否被标记为红色就可以知道它是否出现过了。把这个节点标记为红色,就相当于插入了这个单词。
    这样一来我们询问和插入可以一起完成,所用时间仅仅为单词长度,在这一个样例,便是10。
    我们可以看到,trie树每一层的节点数是26^i级别的。所以为了节省空间。我们用动态链表,或者用数组来模拟动态。空间的花费,不会超过单词数×单词长度。

    杭电AMC 1251 AC code

    class node{
    public:
        int count;
        node *son[26];//存放NODE的指针
        char core;
        node(char core){
            root=false;
            count=0;
            this->core=core;
            for(int i=0;i<26;++i) son[i]=NULL;
        }
        bool root;
        void add(string str,list<node> &trie);
        int getPreNum(string pre);
    };
    
    void node::add(string str, list<node> &trie){
        node *father=this;
        for(unsigned int i=0;i<str.size();++i){
            if(father->son[str[i]-'a']==NULL){
                node newson(str[i]);
                trie.push_back(newson);
                father->son[str[i]-'a']=&trie.back();
            }
            father->count++;
            father=father->son[str[i]-'a'];
        }
        father->count++;
    }
    int node::getPreNum(string pre){
        node *p=this;
        for(unsigned int i=0;i<pre.size();++i){
            if(p->son[pre[i]-'a']==NULL) return 0;
            p=p->son[pre[i]-'a'];
        }
        return p->count;
    }
  • 相关阅读:
    Java回顾之Spring基础
    Java回顾之ORM框架
    Java回顾之JDBC
    Java回顾之一些基础概念
    Java回顾之反射
    Java回顾之序列化
    platform_device与platform_driver
    DB9 公头母头引脚定义及连接
    浅谈UML的概念和模型之UML九种图
    为Windows 7的winsxs目录瘦身,谨慎。
  • 原文地址:https://www.cnblogs.com/iyjhabc/p/2987492.html
Copyright © 2011-2022 走看看