• Trie Tree 字典树


    问题:统计词典中以给定字符串为前缀的单词数量

    http://hihocoder.com/problemset/problem/1014

    (1)数据结构
    cnt:记录词典中所有单词经过该节点的次数
    flag:标识是否构成以该节点结尾的单词
    ptr:指向子节点的指针数组,假设字符集是小写英文字母,ptr[0]!=NULL隐式地表示该节点指向的下一节点对应字符'a'
    根节点不包含字符,其余每个节点只包含一个字符

    (2)插入单词
    待插入的字符串word,指针p指向根节点,下标i指向word[0]
    若字符串为空,不用处理;
    否则,检查word[i]对应的指针p->ptr[word[i]-'a']是否为空;(记该指针为pNext)
    若pNext为空,说明这个字符是第一次在树中出现,为该节点开辟一个新内存,并让pNext指向该新节点;
    若pNext不为空,说明该字符在树中的节点已经建过了,令p = pNext即可;
    把当前p所指的节点的cnt加1
    重复以上过程,word中所有字符都处理完。
    PS:最后,若p->cnt!=0,说明以p指向的节点字符是一个单词的尾部字符。可令p->flag=true。

    对于长度为n的单词,插入单词的时间复杂度为O(n)。

    (3)查询单词(查询前缀)
    待查询单词prefix(若该prefix是一个完整单词,用布尔变量isWord标识它)
    指针p指向根节点,下标i指向prefix[0]
    若单词为空,不用处理;(以空串为前缀的单词数量为0)
    否则,依次匹配每个prefix[i]
    若p->ptr[prefix[i]-'a']为空,说明不存在以prefix为前缀的单词
    若p->ptr[prefix[i]-'a']非空,继续i+1位置的下一次匹配,若直到匹配完prefix中所有字符,这个过程都没有断定匹配失败,也就是匹配成功,最终p指向树中节点的字符就是prefix的尾部字符。
    PS:最后,若p->flag为true,说明prefix是一个完整单词。

    对于长度为n的单词,查询单词的时间复杂度同样为O(n)。

    (4)实现代码

     1 class Trie
     2 {
     3 private:
     4     int cnt;
     5     bool flag;
     6     Trie* ptr[26];
     7 public:
     8     Trie()
     9     {
    10         cnt = 0, flag = false;
    11         memset(ptr,0,sizeof(ptr)); //NULL
    12     }
    13 
    14     void add(const string& word)
    15     {
    16         if(word == "") return;
    17         Trie* p = this;
    18         for(int i = 0; i < word.size(); ++i)
    19         {
    20             int c = word[i] - 'a';
    21             if(p->ptr[c] == NULL)
    22                 p->ptr[c] = new Trie;
    23             p = p->ptr[c];
    24             ++p->cnt;
    25         }
    26         p->flag = true;
    27     }
    28 
    29     int query(const string& prefix, bool& isWord)
    30     {
    31         isWord = false;
    32         if(prefix == "")return 0;
    33         Trie* p = this;
    34         for(int i = 0; i < prefix.size(); ++i)
    35         {
    36             int c = prefix[i] - 'a';
    37             if(p->ptr[c] == NULL)
    38                 return 0;
    39             else
    40                 p = p->ptr[c];
    41         }
    42 
    43         if(p->flag) isWord = true;
    44         return p->cnt;
    45     }
    46 
    47 };

    PS:对字典树进行先序遍历即可对单词进行字典序排序

  • 相关阅读:
    iOS:抽屉侧滑动画两种形式(1、UIView侧滑 2、ViewController侧滑)
    深入浅出 React Native:使用 JavaScript 构建原生应用
    JQuery:通过noConflict()方法同时使用jQuery 和其他框架
    JQuery AJAX: 了解jQuery AJAX
    iOS:iOS开发非常全的三方库、插件等等
    JavaScript:实现瀑布流
    iOS:crash崩溃日志分析
    敏捷开发一千零一夜
    江恩交易战法
    苹果:贩卖高科技的美学体验
  • 原文地址:https://www.cnblogs.com/junjie_x/p/7674336.html
Copyright © 2020-2023  润新知