一.字典树概念

字典树又被称作Trie树,其效率非常高,所以在字符串查找,前缀匹配中应用非常广泛,其高效率是以空间为代价的。典型应用是用于统计和排序大量的字符串,它的优点是,最大限度地减少无谓的字符串比较,查询效率比哈希表更高。

字典树类似于查字典的操作
如果你要在字典中查找单词“Black”,先找到首字母为‘B’的部分,然后再找第二个单词为‘l’的部分······最后,可能可以找到这个单词,当然,也有可能这本词典并没有这个单词。

如图

struct TrieNode {          bool isWord;struct TrieNode [26]children;
}

isWord为true的节点,举个例子,两个字符串"cat"和"catch",字符t和字符h对应的节点,就是红色的(isWord = true)
第二点利用了一个长度为26的TrieNode[]数组,用下标表示字符(char - 'a'),用该下标对应的值表示指向子节点的引用。例如字符串"cat",根节点只有c对应的那个下标(‘c’ - ‘a’ = 2)才是有值的,其余的全为null,表示这条路走不通。

struct TrieNode {        // 节点bool isWord;                               struct TrieNode[26] children ;
TrieNode *TrieInit() {struct TrieNode *root;      // 根节点root->isWord=false;//【向字典树插入单词word】// 思路:按照word的字符,从根节点开始,一直向下走://          如果遇到null,就new出新节点;如果节点已经存在,cur顺着往下走就可以void insert(struct TrieNode *root,char * word) {struct TrieNode *cur = root;                        // 先指向根节点for (int i = 0; i < word.length(); i++) {    // 如果是【后缀树】而不是【前缀树】,把单词倒着插就可以了,即for(len-1; 0; i--)int c = word[i] - 'a';           // (关键) 将一个字符用数字表示出来,并作为下标if (cur.children[c] == null) {cur.children[c] = TrieInit();}cur = cur.children[c];}cur.isWord = true;                          // 一个单词插入完毕,此时cur指向的节点即为一个单词的结尾}//【判断一个单词word是否完整存在于字典树中】// 思路:cur从根节点开始,按照word的字符一直尝试向下走://          如果走到了null,说明这个word不是前缀树的任何一条路径,返回false;//          如果按照word顺利的走完,就要判断此时cur是否为单词尾端:如果是,返回true;如果不是,说明word仅仅是一个前缀,并不完整,返回false
bool search(char *word) {struct TrieNode* cur = root;for (int i = 0; i < word.length(); i++) {int c = word[i] - 'a';if (cur.children[c] == null) {return false;}cur = cur.children[c];}return cur.isWord;}//【判断一个单词word是否是字典树中的前缀】// 思路:和sesrch方法一样,根据word从根节点开始一直尝试向下走://          如果遇到null了,说明这个word不是前缀树的任何一条路径,返回false;//          如果安全走完了,直接返回true就行了———我们并不关心此事cur是不是末尾(isWord)
bool startsWith(char * word) {struct TrieNode *cur = root;for (int i = 0; i < word.length(); i++) {int c = word[i] - 'a';if (cur.children[c] == null) {return false;}cur = cur.children[c];}return true;}
}

例题

在英语中,我们有一个叫做 词根(root) 的概念,可以词根后面添加其他一些词组成另一个较长的单词——我们称这个词为 继承词(successor)。例如,词根an,跟随着单词 other(其他),可以形成新的单词 another(另一个)。

现在,给定一个由许多词根组成的词典 dictionary 和一个用空格分隔单词形成的句子 sentence。你需要将句子中的所有继承词用词根替换掉。如果继承词有许多可以形成它的词根,则用最短的词根替换它。

你需要输出替换之后的句子。

#define MAX_STR_LEN 1024typedef struct Trie {bool isEnd;struct Trie *children[26];
} Trie;Trie * creatTrie() {Trie *node = (Trie *)malloc(sizeof(Trie));for (int i = 0; i < 26; i++) {node->children[i] = NULL;}node->isEnd = false;return node;
}void freeTrie(Trie *root) {for (int i = 0; i < 26; i++) {if (root->children[i]) {freeTrie(root->children[i]);}}free(root);
}char *findRoot(const char *word, Trie *trie) {char *root = (char *)malloc(sizeof(char) * MAX_STR_LEN);Trie *cur = trie;int len = strlen(word);int pos = 0;for (int i = 0; i < len; i++) {char c = word[i];if (cur->isEnd) {root[pos] = 0;return root;}if (!cur->children[c - 'a']) {free(root);return word;}root[pos++] = c;cur = cur->children[c - 'a'];}root[pos] = 0;return root;
}char ** split(char *str, char ch, int *returnSize) {int len = strlen(str);char **res = (char **)malloc(sizeof(char *) * len);int i = 0, pos = 0;while (i < len) {while (i < len && str[i] == ch) {i++;}int start = i;while (i < len && str[i] != ch) {i++;}if (start < len) {res[pos] = (char *)malloc(sizeof(char) * (i - start + 1));memcpy(res[pos], str + start, sizeof(char) * (i - start));res[pos][i - start] = '\0';pos++;}}*returnSize = pos;return res;
}char * replaceWords(char ** dictionary, int dictionarySize, char * sentence){Trie *trie = creatTrie();for (int i = 0; i < dictionarySize; i++) {Trie *cur = trie;int len = strlen(dictionary[i]);for (int j = 0; j < len; j++) {char c = dictionary[i][j];if (!cur->children[c - 'a']) {cur->children[c - 'a'] = creatTrie();}cur = cur->children[c - 'a'];}cur->isEnd = true;}int wordsSize = 0, pos = 0;char **words = split(sentence, ' ', &wordsSize);char *ans = (char *)malloc(sizeof(char) * (strlen(sentence) + 2));for (int i = 0; i < wordsSize; i++) {char * ret = findRoot(words[i], trie);pos += sprintf(ans + pos, "%s ", ret);free(words[i]);if (ret != words[i]) {free(ret);}}ans[pos - 1] = '\0';freeTrie(trie);return ans;
}作者:LeetCode-Solution
链接:https://leetcode.cn/problems/replace-words/solution/dan-ci-ti-huan-by-leetcode-solution-pl6v/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

字典树学习 根据前缀词根建立字典树相关推荐

  1. [湖南集训]更为厉害 树上主席树-以树深度为下下标建立主席树

    题意题解: 首先对于树上某个点a来说,假设点b是a的祖先(也就是在a的上面),那么答案很好计算,也就是min(k,dep[a]−1)∗(size[a]−1)min(k,dep[a]-1)*(size[ ...

  2. 英汉小字典java_java 学习案例之英汉字典

    在写代码的时候,当鼠标悬浮在某一个单词上面的时候,有道词典点有时会弹出一个消息气泡,在里面中给出关于这个单词相关的解释,下面给大家展示一个使用Java基础语言编写的英汉字典案例: 实现功能: 输入英文 ...

  3. 可以学习的英语和日语字典

    作者:http://blog.csdn.net/flower_garden 本英文字典和日文字典仅为学习方便使用,作者和下列提到的网站没有任何关系. 下载地址:http://pan.baidu.com ...

  4. 分门别类刷leetcode——高级数据结构(字典树,前缀树,trie树,并查集,线段树)

    目录 Trie树(字典树.前缀树)的基础知识 字典树的节点表示 字典树构造的例子 字典树的前序遍历 获取字典树中全部单词 字典树的整体功能 字典树的插入操作 字典树的搜索操作 字典树的前缀查询 字典树 ...

  5. 字典树(Trie/前缀树)

    目录 字典树的概念 字典树的逻辑 字典树的实现 易混点剖析 代码示例 字典树的概念 字典树(Trie)是一种空间换时间的数据结构,是一棵关于"字典"的树.主要用于统计.排序和保存大 ...

  6. 【算法学习】前缀树Trie

    Tire(前缀树) 一.定义: Trie(发音类似 "try")或者说前缀树是一种树形数据结构,用于高效地存储和检索字符串数据集中的键. 其核心是使用「边」来代表有无字符,使用「点 ...

  7. Swift基础入门知识学习(7)-字典-讲给你懂

    Swift基础入门知识学习(6)-数组(阵列)-讲给你懂 目录 声明字典 创建一个空字典 存取与修改字典 使用for-in遍历字典中的所有值 字典转换为数组 Swift字典(dictionary) 用 ...

  8. python字典里可以放列表吗_学习python之列表及字典

    本关学习的是两种新的数据类型:列表.字典. 在开始之前先学习一下计算机与数据直接的关系. 计算机有3种方式利用数据: 1.直接使用数据 print('我来了') 2.计算和加工数据 print (1+ ...

  9. Python语言学习:利用sorted对字典按照value进行递减排序,输出列表,并给定排名索引,组成新字典输出

    Python语言学习:利用sorted对字典按照value进行递减排序,输出列表,并给定排名索引,组成新字典输出 目录 利用sorted对字典按照value进行递增排序,输出列表,并给定排名索引,组成 ...

最新文章

  1. Mac Os 基本命令行
  2. Java ReentrantLock 详解
  3. 每日一皮:开会不关微信的尴尬(2)
  4. 多个切点 boot spring_全网独家Spring/Cloud/MVC/Boot,脑图+面试+进阶,就问你服不服?...
  5. P1801 黑匣子_NOI导刊2010提高(06)
  6. Eclipse反编译插件: Jodeclipse与JadClipse
  7. 利用python进行数据分析第二版pdf百度云_参考《利用Python进行数据分析(第二版)》高清中文PDF+高清英文PDF+源代码...
  8. HDU 3549 Flow Problem
  9. L1-036 A乘以B
  10. 关于卡巴斯基6.0自动升级时报错后自动退出的情况
  11. 嵌入式Linux系统编程学习之十一Linux进程的创建与控制
  12. hbase建表语句_HBase 中文参考指南真不少~
  13. 设计模式之Facade---外观模式
  14. 推荐一份 Google 面试指南
  15. 关于更换PC版浏览器推荐
  16. JAFFE表情库介绍
  17. Vue3+elementplus搭建通用管理系统实例五:后台主页搭建上
  18. php7关闭缓存、禁用缓存
  19. 拒绝丧偶式育儿,正确「养育男孩」
  20. WAF - SQL注入之绕过云锁 靶场实战

热门文章

  1. 概率论基础知识(三) 参数估计
  2. LuoguP4313 BZOJ3894 文理分科——最小割
  3. Linux oracle 怎么安装,oracle在linux下怎么安装
  4. 飞腾桌面腾锐D2000 核心板
  5. 【2017级面向对象程序设计】第3、4次成绩及排名
  6. 利用百度地图服务发布自己制作图片的地图
  7. raptor累乘流程图_程序设计基础
  8. kali 桥接上网_kali新手入门教学(16)--如何在校园网下使用桥接模式上网
  9. 【SQL注入】CTF练习题WriteUp——“百度杯”CTF比赛 九月场SQL
  10. 9宫格实现微信朋友圈图片点击放大缩小弹簧效果