关于前缀树的一些题目
关于前缀树的一些题目
1、实现前缀树
-
描述:
请你实现 Trie 类:
Trie() 初始化前缀树对象。
void insert(String word) 向前缀树中插入字符串 word 。
boolean search(String word) 如果字符串 word 在前缀树中,返回 true(即,在检索之前已经插入);否则,返回 false 。
boolean startsWith(String prefix) 如果之前已经插入的字符串 word 的前缀之一为 prefix ,返回 true ;否则,返回 false 。 -
解法:
1、构造字典树:包含以下两个字段:
-
指向子节点的指针数组 son。对于本题而言,数组长度为26,即小写英文字母的数量。此时 son[0] 对应小写字母 a,son[1] 对应小写字母 b,…,son[25] 对应小写字母 z。
-
布尔字段 isEnd,表示该节点是否为字符串的结尾。
2、插入函数:
-
当插入一个字符时,如果这个字符不存在,就在当前节点的 son 数组中加入一个新的节点。
-
如果存在,就继续向下遍历下一个字符。
3、搜索字符串:
-
对当前字符串的每一个字符进行遍历,如果字典树中含有这个字符,就继续下一个字符,直到字符串结束或者前缀树当前节点 isEnd 为 true
-
如果不含这个字符,就直接 return false;
4、搜索前缀:
-
与搜索字符差不多,只要求含有这个前缀就好了,不是完全符合。
-
-
源码:
class Trie { private Trie[] son; private boolean isEnd; /** Initialize your data structure here. */ public Trie() { son = new Trie[26]; isEnd = false; } /** Inserts a word into the trie. */ public void insert(String word) { Trie node = this; for(int i=0; i<word.length(); i++){ int index = word.charAt(i)-'a'; if(node.son[index] == null){ node.son[index] = new Trie(); } node = node.son[index]; } node.isEnd = true; } /** Returns if the word is in the trie. */ public boolean search(String word) { Trie node = searchWord(word); //有不相等 或者 未到结尾都是 false return node!=null && node.isEnd; } /** Returns if there is any word in the trie that starts with the given prefix. */ public boolean startsWith(String prefix) { //未到结尾也可以 return (searchWord(prefix)!=null); } /*搜索函数本体*/ public Trie searchWord(String word){ Trie node = this; for(int i=0; i<word.length(); i++){ int index = word.charAt(i)-'a'; //不相等了,就是有不相等的字符在 word 遍历完之前 if(node.son[index] == null){ return null; } node = node.son[index]; } return node; } }
2、替换单词
-
描述:
在英语中,我们有一个叫做 词根(root) 的概念,可以词根后面添加其他一些词组成另一个较长的单词——我们称这个词为 继承词(successor)。例如,词根an,跟随着单词 other(其他),可以形成新的单词 another(另一个)。
现在,给定一个由许多词根组成的词典 dictionary 和一个用空格分隔单词形成的句子 sentence。你需要将句子中的所有继承词用词根替换掉。如果继承词有许多可以形成它的词根,则用最短的词根替换它。
你需要输出替换之后的句子。
-
解法:
有了上题的经验,很容易想到使用前缀树为提供的词根建立前缀树,但是这里一个词根结束的标记,我们不能再使用 isEnd 来标记。如果结果是以词根开头的话,我们要取得词根本身,而不是一个结束标记。所以这里使用一个字符串来标记结束。
-
源码:
class Solution { private TrieNode root = new TrieNode(); public String replaceWords(List<String> dictionary, String sentence) { //将字典插入树 for(int i=0; i<dictionary.size(); i++){ String str = dictionary.get(i); TrieNode node = root; for(int j=0; j<str.length(); j++){ int index = str.charAt(j)-'a'; if(node.son[index] == null){ node.son[index] = new TrieNode(); } node = node.son[index]; } //把完整的词根加进叶子节点 node.word = str; } //对 sentence 进行遍历 StringBuilder res = new StringBuilder(); for(String s : sentence.split("\\s+")){ if(res.length()>0) res.append(" "); TrieNode node = root; for(int i=0; i<s.length(); i++){ int index = s.charAt(i)-'a'; //如果 node.son[index]==null,就说明没有这个字符,直接把 s 加进 res 中 //如果 node.word!=null 就说明这个 s 是含有词根的,直接把词根加进 res 就好了 if(node.son[index] == null || node.word!=null) break; node = node.son[index]; } res.append(node.word!=null ? node.word : s); } return res.toString(); } } class TrieNode{ TrieNode[] son; //使用字符串来标记结束 String word; public TrieNode(){ //不对字符串进行初始化,用以判断含有词根的结束 son = new TrieNode[26]; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)