一、题目描述
在英语中,有一个叫做 词根(root) 的概念,它可以跟着其他一些词组成另一个较长的单词——我们称这个词为 继承词(successor)。例如,词根an,跟随着单词 other(其他),可以形成新的单词 another(另一个)。
现在,给定一个由许多词根组成的词典和一个句子,需要将句子中的所有继承词用词根替换掉。如果继承词有许多可以形成它的词根,则用最短的词根替换它。
需要输出替换之后的句子。
输入:dictionary = [“cat”,“bat”,“rat”], sentence = “the cattle was rattled by the battery”
输出:“the cat was rat by the bat”
二、 代码思路
很显然本题属于前缀树的应用
我们可以将词根存入前缀树,并在结束位置加上 end = true
我们可以对sentence(继承词)逐个遍历,观察改词是否在前缀树中有前缀。
如果有的话就替换,没有的话就原样输出。
这样的代码思路实际上有两种实现方法:
1、传统的维护一棵前缀树,使用 children[26] 孩子数组,来存储各个节点。
2、我们使用Hash来维护前缀树。
3、直接使用Hash表
首先将dictionary 中所有词根放入哈希集合中,然后对于 sentence 中的每个单词,由短至长遍历它所有的前缀,如果这个前缀出现在哈希集合中,则我们找到了当前单词的最短词根,将这个词根替换原来的单词。最后返回重新拼接的句子。
作者:LeetCode-Solution
三、 代码题解
class Solution {
public String replaceWords(List<String> dictionary, String sentence) {
//很显然本题属于前缀树的应用
//我们可以将词根存入前缀树,并在结束位置加上 end = true
//我们可以对sentence(继承词)逐个遍历,观察改词是否在前缀树中有前缀。
//如果有的话就替换,没有的话就原样输出。
Trie trie = new Trie();
//加入前缀树中
for (String word : dictionary) {
trie.insert(word);
}
//判断sentence是否在前缀树中
String words[] = sentence.split(" ");
String res = "";
for (int i = 0; i < words.length; i++) {
String word = trie.getPrefixFromWord(words[i]);
if (i == words.length - 1) {
res += word;
} else {
res += word + " ";
}
}
return res;
}
}
class Trie {
//创建一个子节点数组,大小为26个,分别对应26个英文字母
//但是该node节点对象并没有表示当前该节点存放的英文字母是什么
//而是,利用数组26个大小区域是否为空 来判断对应的字符是否存在。
private Trie[] children;
private boolean isEnd;
/** Initialize your data structure here. */
public Trie() {
children = new Trie[26];
isEnd = false;
}
/** Inserts a word into the trie. */
public void insert(String word) {
//将当前对象作为一个节点
//每个对象节点都有26个子节点
Trie node = this;
for (int i = 0; i < word.length(); i++) {
char ch = word.charAt(i);
//相当于给以该节点为父节点的孩子节点赋值,因为通过某个字符可以找到对应的孩子节点
int index = ch - 'a';
if (node.children[index] == null) {
node.children[index] = new Trie();
}
node = node.children[index];
}
node.isEnd = true;
}
/** Returns if the word is in the trie. */
public boolean search(String word) {
Trie node = searchPrefix(word);
//如果最后字符存在的node节点不为空,而且这个节点正好也是结束点,那么之前遍历的路径
//连在一起就是一个目标字符
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 searchPrefix(prefix) != null;
}
private Trie searchPrefix(String prefix) {
Trie node = this;
for (int i = 0; i < prefix.length(); i++) {
char ch = prefix.charAt(i);
int index = ch - 'a';
if (node.children[index] == null) {
return null;
}
node = node.children[index];
}
return node;
}
//定义新方法,判断某个单词是否在前缀树中存在前缀,并返回前缀
public String getPrefixFromWord(String word) {
Trie node = this;
String res = "";
for (int i = 0; i < word.length(); i++) {
//判断前缀树中是否有一个前缀,该前缀正好是该单词的前缀
char ch = word.charAt(i);
int index = ch - 'a';
if (node.children[index] == null) {
return word;
}
res += ch;
node = node.children[index];
if (node.isEnd == true) {
return res;
}
}
return word;
}
}
Hash表实现:
class Solution {
public String replaceWords(List<String> dictionary, String sentence) {
Set<String> dictionarySet = new HashSet<String>();
for (String root : dictionary) {
dictionarySet.add(root);
}
String[] words = sentence.split(" ");
for (int i = 0; i < words.length; i++) {
String word = words[i];
for (int j = 0; j < word.length(); j++) {
if (dictionarySet.contains(word.substring(0, 1 + j))) {
words[i] = word.substring(0, 1 + j);
break;
}
}
}
return String.join(" ", words);
}
}
作者:LeetCode-Solution
链接:https://leetcode.cn/problems/UhWRSj/solution/ti-huan-dan-ci-by-leetcode-solution-9reh/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。