• 字典树(trie树) 后缀树 广义后缀树


    转自:http://www.cnblogs.com/dong008259/archive/2011/11/11/2244900.html
    (1)字典树(Trie树)

      Trie是个简单但实用的数据结构,通常用于实现字典查询。我们做即时响应用户输入的AJAX搜索框时,就是Trie开始。本质上,Trie是一颗存储多个字符串的树。相邻节点间的边代表一个字符,这样树的每条分支代表一则子串,而树的叶节点则代表完整的字符串。和普通树不同的地方是,相同的字符串前缀共享同一条分支。还是例子最清楚。给出一组单词,inn, int, at, age, adv, ant, 我们可以得到下面的Trie:
    这里写图片描述
    可以看出:
    •每条边对应一个字母。
    •每个节点对应一项前缀。叶节点对应最长前缀,即单词本身。
    •单词inn与单词int有共同的前缀“in”, 因此他们共享左边的一条分支,root->i->in。同理,ate, age, adv, 和ant共享前缀”a”,所以他们共享从根节点到节点”a”的边。
    •查询非常简单。比如要查找int,顺着路径i -> in -> int就找到了。
    •搭建Trie的基本算法也很简单,无非是逐一把每则单词的每个字母插入Trie。插入前先看前缀是否存在。如果存在,就共享,否则创建对应的节点和边。比如要插入单词add,就有下面几步:•考察前缀”a”,发现边a已经存在。于是顺着边a走到节点a。
    •考察剩下的字符串”dd”的前缀”d”,发现从节点a出发,已经有边d存在。于是顺着边d走到节点ad
    •考察最后一个字符”d”,这下从节点ad出发没有边d了,于是创建节点ad的子节点add,并把边ad->add标记为d。

    //copyright: www.acmerblog.com
    
    #include <stdio.h>
    #include <iostream>
    using namespace std;
    #define  MAX    26
    
    typedef struct TrieNode
    {
        int nCount;  // 该节点前缀 出现的次数
        struct TrieNode *next[MAX]; //该节点的后续节点
    } TrieNode;
    
    TrieNode Memory[1000000]; //先分配好内存。 malloc 较为费时
    int allocp = 0;
    
    //初始化一个节点。nCount计数为1, next都为null
    TrieNode * createTrieNode()
    {
        TrieNode * tmp = &Memory[allocp++];
        tmp->nCount = 1;
        for (int i = 0; i < MAX; i++)
            tmp->next[i] = NULL;
        return tmp;
    }
    
    void insertTrie(TrieNode * * pRoot, char * str)
    {
        TrieNode * tmp = *pRoot;
        int i = 0, k;
        //一个一个的插入字符
        while (str[i])
        {
            k = str[i] - 'a'; //当前字符 应该插入的位置
            if (tmp->next[k])
            {
                tmp->next[k]->nCount++;
            }
            else
            {
                tmp->next[k] = createTrieNode();
            }
    
            tmp = tmp->next[k];
            i++; //移到下一个字符
        }
    
    }
    
    int searchTrie(TrieNode * root, char * str)
    {
        if (root == NULL)
            return 0;
        TrieNode * tmp = root;
        int i = 0, k;
        while (str[i])
        {
            k = str[i] - 'a';
            if (tmp->next[k])
            {
                tmp = tmp->next[k];
            }
            else
                return 0;
            i++;
        }
        return tmp->nCount; //返回最后的那个字符  所在节点的 nCount
    }
    
    int main(void)
    {
        char s[11];
        TrieNode *Root = createTrieNode();
        while (gets(s) && s[0] != '0') //读入0 结束
        {
            insertTrie(&Root, s);
        }
    
        while (gets(s)) //查询输入的字符串
        {
            printf("%d
    ", searchTrie(Root, s));
        }
    
        return 0;
    }

    (2)后缀树

      所谓后缀树,就是包含一则字符串所有后缀的压缩了的字典树。先说说后缀的定义。给定一长度为n的字符串S=S1S2..Si..Sn,和整数i,1 <= i <= n,子串SiSi+1…Sn都是字符串S的后缀。以字符串S=XMADAMYX为例,它的长度为8,所以S[1..8], S[2..8], … , S[8..8]都算S的后缀,我们一般还把空字串也算成后缀。这样,我们一共有如下后缀。对于后缀S[i..n],我们说这项后缀起始于i。
    1.S[1..8], XMADAMYX, 也就是字符串本身,起始位置为1
    2.S[2..8], MADAMYX,起始位置为2
    3.S[3..8], ADAMYX,起始位置为3
    4.S[4..8], DAMYX,起始位置为4
    5.S[5..8], AMYX,起始位置为5
    6.S[6..8], MYX,起始位置为6
    7.S[7..8], YX,起始位置为7
    8.S[8..8], X,起始位置为8
    9.空字串。记为$。

    所有这些后缀字符串组成一棵字典树:
    这里写图片描述
    仔细观察上图,我们可以看到不少值得压缩的地方。比如蓝框标注的分支都是独苗,没有必要用单独的节点同边表示。如果我们允许任意一条边里包含多个字母,就可以把这种没有分叉的路径压缩到一条边。另外每条边已经包含了足够的后缀信息,我们就不用再给节点标注字符串信息了。我们只需要在叶节点上标注上每项后缀的起始位置。于是我们得到下图:
    这里写图片描述
    这样的结构丢失了某些后缀。比如后缀X在上图中消失了,因为它正好是字符串XMADAMYX的前缀。为了避免这种情况,我们也规定每项后缀不能是其它后缀的前缀。要解决这个问题其实挺简单,在待处理的子串后加一个空字串就行了。例如我们处理XMADAMYX前,先把XMADAMYX变为 XMADAMYX$,于是就得到suffix tree。

    这里写图片描述
    这就形成一棵后缀树了。关于如何建立一棵后缀树,已有很成熟的算法,能在o(n)时间内解决。

    (3)广义后缀树

      传统的后缀树只能处理一个单词的所有后缀。广义后缀树存储任意多个单词的所有后缀。例如字符串“abab”和“baba”,首先将它们使用特殊结束符链接起来,如表示成“ababbaba#”,然后求连接后的新字符的后缀树,遍历所得后缀树,如遇到特殊字符,如“”,”#”等则去掉以该节点为跟的子树,最后所得后缀树即为原字符串组的广义后缀树。其实质是将两个字符串的所有后缀,即:abab,bab,ab,b,baba#,aba#,ba#,a#,组成字典树,再进行压缩处理。广义后缀树的一个常应用就是判断两个字符串的相识度。

  • 相关阅读:
    Femap和NX Nastran简介 / Introduction of Femap and NX Nastran
    WINDOWS蓝屏错误对照表[z]
    Matlab 样条工具箱(Spline ToolBox)[z]
    NumPy 简介
    NX Nastran[z]
    UG后处理实例讲解
    NumPy for Matlab Users【z】
    PyMat An interface between Python and MATLAB
    ANSYS Workbench Products Installation and Configuration Guide
    NumPy使用手记[z]
  • 原文地址:https://www.cnblogs.com/luckycode/p/5255646.html
Copyright © 2020-2023  润新知