算法总结
package com.chenghaixiang.jianzhi2.day21; /** * @author 程海翔 * @school 石家庄铁道大学 */ public class Office062 { } //Trie(发音类似 "try")或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补完和拼写检查。 // //请你实现 Trie 类: // // Trie() 初始化前缀树对象。 // void insert(String word) 向前缀树中插入字符串 word 。 // boolean search(String word) 如果字符串 word 在前缀树中,返回 true(即,在检索之前已经插入);否则,返回 false 。 // boolean startsWith(String prefix) 如果之前已经插入的字符串 word 的前缀之一为 prefix ,返回 true ;否则,返回 false 。 //Trie 是一颗多叉树模型,即每个结点的分支数量可能为多个。前缀树 class Trie { //根节点 TreeNode root; class TreeNode{ //26个字节点,表示26个小写字母 TreeNode[] childnext; //表示这个节点是否为最后一个字符 boolean isEnd; TreeNode() { isEnd=false; childnext=new TreeNode[26]; } } /** Initialize your data structure here. */ public Trie() { root=new TreeNode(); } /** Inserts a word into the trie. */ public void insert(String word) { //从根节点开始遍历 TreeNode cur=root; for (char ch:word.toCharArray()){ //如果当前子结点为null,开辟子结点的子结点,相当于插入这个字符 if(cur.childnext[ch-'a']==null){ cur.childnext[ch-'a']=new TreeNode(); } //继续插入下一个节点 cur=cur.childnext[ch-'a']; } // 将最后一个字符设置为结尾 cur.isEnd=true; } /** Returns if the word is in the trie. */ public boolean search(String word) { TreeNode cur=root; for (char ch:word.toCharArray()){ //对应结点为空证明没有这个字符,直接返回false if(cur.childnext[ch-'a']==null){ return false; } cur=cur.childnext[ch-'a']; } // 检查最后一个字符是否是结尾 //比如前缀树插入了apple,传入参数是app,在for循环时if条件都不满足,但在cur.isEnd时因为当前值是false,所以返回false return cur.isEnd; } // 查找前缀 /** Returns if there is any word in the trie that starts with the given prefix. */ public boolean startsWith(String prefix) { TreeNode cur=root; for(char ch:prefix.toCharArray()){ if(cur.childnext[ch-'a']==null){ return false; } cur=cur.childnext[ch-'a']; } return true; } }
package com.chenghaixiang.jianzhi2.day21; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @author 程海翔 * @school 石家庄铁道大学 */ public class Office063 { } //在英语中,有一个叫做 词根(root) 的概念,它可以跟着其他一些词组成另一个较长的单词——我们称这个词为 继承词(successor)。例如,词根an,跟随着单词 other(其他),可以形成新的单词 another(另一个)。 // //现在,给定一个由许多词根组成的词典和一个句子,需要将句子中的所有继承词用词根替换掉。如果继承词有许多可以形成它的词根,则用最短的词根替换它。 // //需要输出替换之后的句子。 class Solution { class Trie{ //前缀树 Map<Character,Trie> children; Trie() { children=new HashMap<>(); } } public String replaceWords(List<String> dictionary, String sentence) { Trie trie=new Trie(); for (String word:dictionary){ Trie cur=trie; //将字典放入前缀树 for(int i=0;i<word.length();i++){ char c=word.charAt(i); //put在放入数据时,如果放入数据的key已经存在与Map中,最后放入的数据会覆盖之前存在的数据, // //而putIfAbsent在放入数据时,如果存在重复的key,那么putIfAbsent不会放入值。 cur.children.putIfAbsent(c,new Trie()); cur=cur.children.get(c); } //字典中各个单词结尾 cur.children.put('#',new Trie()); } String[] words=sentence.split(" "); for(int i=0;i<words.length;i++){ words[i]=findRoot(words[i],trie); } return String.join(" ",words); } //对字符串按字典进行处理,继承词用词根替换掉 String findRoot(String words,Trie trie){ StringBuffer root=new StringBuffer(); Trie cur=trie; for (int i=0;i<words.length();i++){ char c=words.charAt(i); if(cur.children.containsKey('#')){ return root.toString(); } if (!cur.children.containsKey(c)){ return words; } root.append(c); cur=cur.children.get(c); } return root.toString(); } }