• Trie三兄弟——标准Trie、压缩Trie、后缀Trie


    1.Trie导引

    Trie树是一种基于树的数据结构,又称单词查找树、前缀树,字典树,是一种哈希树的变种。应用于字符串的统计与排序,经常被搜索引擎系统用于文本词频统计。用于存储字符串以便支持快速模式匹配,主要应用在信息检索中,Trie支持的主要查询操作是模式匹配和前缀匹配。Trie树可以看着是一个确定有限状态自动机,有限状态自动机另一篇博文字符串模式匹配算法——BM、Horspool、Sunday、KMP、KR、AC算法一网打尽 有介绍。

    计算机科学中,trie,又称前缀树,是一种有序,用于保存关联数组,其中的键通常是字符串二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定。一个节点的所有子孙都有相同的前缀,也就是这个节点对应的字符串,而根节点对应空字符串。一般情况下,不是所有的节点都有对应的值,只有叶子节点和部分内部节点所对应的键才有相关的值

    Trie 这个术语来自于 retrieval。根据词源学,trie 的发明者 Edward Fredkin 把它读作 /ˈtr/ "tree"。[1][2] 但是,其他作者把它读作 /ˈtr/ "try"。[1][2][3](算法导论也叫做做基数树radix树或retrieval 树)

    在图示中,键标注在节点中,值标注在节点之下。每一个完整的英文单词对应一个特定的整数。Trie 可以看作是一个确定有限状态自动机,尽管边上的符号一般是隐含在分支的顺序中的。

    键不需要被显式地保存在节点中。图示中标注出完整的单词,只是为了演示 trie 的原理。

    trie 中的键通常是字符串,但也可以是其它的结构。trie 的算法可以很容易地修改为处理其它结构的有序序列,比如一串数字或者形状的排列。比如,bitwise trie 中的键是一串位元,可以用于表示整数或者内存地址

    2.标准Trie

    令S是取自字母表∑的s个集合,满足S中不存在一个串是另一个串的前缀。S的一个标准Trie(standard trie)是一颗有序书T,满足如下性质:

    • 除了根之外,T中的每个结点标记有∑的一个字符。
    • T中一个内部结点的子结点的次序有字母表∑上的规范次序确定。
    • T有s个外部结点(叶结点),每个外部结点关联S中的一个串,满足从根到T中一个外部结点v的路径上标记连接产生S中关联的一个串。

    下图是串{bear,bell,bid,bull,buy,sell,stock,stop}的标准Trie

    #include<algorithm>
    #include<iostream>
    using namespace std;
    
    const int sonnum=26,base='a';
    struct Trie
    {
        int num;//to remember how many word can reach here,that is to say,prefix
        bool terminal;//If terminal==true ,the current point has no following point
        struct Trie *son[sonnum];//the following point
    };
    Trie *NewTrie()// create a new node
    {
        Trie *temp=new Trie;
        temp->num=1;temp->terminal=false;
        for(int i=0;i<sonnum;++i)temp->son[i]=NULL;
        return temp;
    }
    void Insert(Trie *pnt,char *s,int len)// insert a new word to Trie tree
    {
        Trie *temp=pnt;
        for(int i=0;i<len;++i)
        {
             if(temp->son[s[i]-base]==NULL)
                 temp->son[s[i]-base]=NewTrie();
             else
                 temp->son[s[i]-base]->num++;
    
             temp=temp->son[s[i]-base];
        }
        temp->terminal=true;
    
    }
    
    
    void Delete(Trie *pnt)// delete the whole tree
    {
        if(pnt!=NULL)
        {
            for(int i=0;i<sonnum;++i)if(pnt->son[i]!=NULL)Delete(pnt->son[i]);
            delete pnt; 
            pnt=NULL;
        }
    }
    Trie* Find(Trie *pnt,char *s,int len)//trie to find the current word
    {
        Trie *temp=pnt;
        for(int i=0;i<len;++i)
        {
            if(temp->son[s[i]-base]!=NULL)
            {
                cout<<temp->son[s[i]-base]->num<<ends<<s[i]<<endl;//没有打印根节点的num
                temp=temp->son[s[i]-base];
            }
            else return NULL;
        }
        return temp;
    } 
     
    
     
    int main()
    {
        Trie *root;
        root=NewTrie();
        Insert(root,"bear",4);
        Insert(root,"bell",4);
         Insert(root,"bid",3);
         Insert(root,"bull",4);
         Insert(root,"buy",3);
    
        Trie *res;
        res=Find(root,"bear",4);
        if(res!=NULL)
        {
                cout<<res->terminal;
        }
        else
            cout<<"not found";
    }

    输出:

    5 b

    2 3

    1 a

    1 r

    1 找到了。(代码参考:http://hi.baidu.com/luyade1987/item/7c1977f5e9015cdf6225d224)

    储总长为n,来自大小为d的字母表中s个串的集合S的标准Trie具有如下性质

    1. T中每个内部结点最多有d个子结点。
    2. T有s个外部结点。(显然,有s个串)
    3. T的高度等于最长串的长度。
    4. T中的结点书为O(n)。

    性能:对于有n个英文字母的串来说,在内部结点中定位指针所需要花费O(d)时间,d为字母表的大小,英文为26。由于在上面的算法中内部结点指针定位使用了数组随机存储方式,因此时间复杂度降为了O(1)。但是如果是中文字,下面在实际应用中会提到。因此我们在这里还是用O(d)。 查找成功的时候恰好走了一条从根结点到叶子结点的路径。因此时间复杂度为O(d*n)。但是,当查找集合X中所有字符串两两都不共享前缀时,trie中出现最坏情况。除根之外,所有内部结点都自由一个子结点。此时的查找时间复杂度蜕化为O(d*(n^2))

    Trie树的特点如下
    1)根节点不包含字符,除根节点外每一个节点都只包含一个字符
    2)从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
    3)每个节点的所有子节点包含的字符都不相同。(也就是孩子都不相同)
     
    http://dsqiu.iteye.com/blog/1705697

    http://en.wikipedia.org/wiki/Trie

    http://blog.csdn.net/v_july_v/article/details/6897097

  • 相关阅读:
    iOS 获取当前界面所在的视图控制器
    the executable was signed with invalid 解决方法
    iOS 中一些代码规范
    In order to validate a domain name for self signed certificates, you MUST use pinning,AFNetWorking使用自签证书时出现问题。
    IOS -- SQLite数据库判断表是否存在
    如何解决 iOS The document “(null)” requires Xcode 8.0 or later. 不能编译的问题
    iOS开发 如何适配iOS10
    更新cocoapods之后,出现Undefined symbols for architecture arm64
    新的一天
    css布局之弹性布局
  • 原文地址:https://www.cnblogs.com/youxin/p/3301411.html
Copyright © 2020-2023  润新知