[LeetCode][720] Longest Word in Dictionary题解
标签:tire / hash / 剪枝
题意:找到最长的单词,该单词要在数组中拥有一个前缀,满足该前缀也是在数组中。如果有相同长度返回字典序小的。也就是返回最长的字典序最小的字符串。
这里我们使用了前缀树数据结构。
首先对数组进行排序,排序规则为长的在前面,如果相同长度,字典序小的在前面。
对于一组字符串,把遍历加入到前缀树中。
然后,对排序过后的vector<string>
数组进行遍历,如果找到一个单词在前缀树中有前缀则返回该单词。
核心代码:
bool startsWith(string prefix)
{
TrieNode *p = root;
for (auto &a : prefix)
{
int i = a - 'a';
if (!p->child[i])
{
return false;
}
p = p->child[i];
if (!p->isWord)
{
return false;
}
}
//如果是加入了单词则需要判断是不是被标记为isword
//这里是找是不是前缀因此不需要标记isword
return true;
}
思路参考自:https://zxi.mytechroad.com/blog/string/leetcode-720-longest-word-in-dictionary/
AC代码
/*
* [720] Longest Word in Dictionary
*
* https://leetcode.com/problems/longest-word-in-dictionary/description/
*
* algorithms
* Easy (42.29%)
* Total Accepted: 23.7K
* Total Submissions: 56K
* Testcase Example: '["w","wo","wor","worl","world"]'
*
* Given a list of strings words representing an English Dictionary, find the
* longest word in words that can be built one character at a time by other
* words in words. If there is more than one possible answer, return the
* longest word with the smallest lexicographical order. If there is no
* answer, return the empty string.
*
* Example 1:
*
* Input:
* words = ["w","wo","wor","worl", "world"]
* Output: "world"
* Explanation:
* The word "world" can be built one character at a time by "w", "wo", "wor",
* and "worl".
*
*
*
* Example 2:
*
* Input:
* words = ["a", "banana", "app", "appl", "ap", "apply", "apple"]
* Output: "apple"
* Explanation:
* Both "apply" and "apple" can be built from other words in the dictionary.
* However, "apple" is lexicographically smaller than "apply".
*
*
*
* Note:
* All the strings in the input will only contain lowercase letters.
* The length of words will be in the range [1, 1000].
* The length of words[i] will be in the range [1, 30].
*
*/
class TrieNode
{
public:
TrieNode *child[26];
bool isWord;
TrieNode() : isWord(false)
{
for (auto &a : child)
{
a = NULL;
}
}
};
class Trie
{
private:
TrieNode *root;
public:
// 1、对每个结点开一个字母集大小的数组,对应的下标是儿子所表示的字母,
// 内容则是这个儿子对应在大数组上的位置,即标号;
// 2、对每个结点挂一个链表,按一定顺序记录每个儿子是谁;
// 3、使用左儿子右兄弟表示法记录这棵树。
/** Initialize your data structure here. */
Trie()
{
root = new TrieNode();
}
/** Inserts a word into the trie. */
void insert(string word)
{
TrieNode *p = root;
for (auto &a : word)
{
int i = a - 'a';
if (!p->child[i])
{
p->child[i] = new TrieNode();
}
p = p->child[i];
}
//退出时候已经达到树的末尾
p->isWord = true;
}
/** Returns if the word is in the trie. */
bool search(string word)
{
TrieNode *p = root;
for (auto &a : word)
{
int i = a - 'a';
if (!p->child[i])
{
return false;
}
p = p->child[i];
}
return p->isWord;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
bool startsWith(string prefix)
{
TrieNode *p = root;
for (auto &a : prefix)
{
int i = a - 'a';
if (!p->child[i])
{
return false;
}
p = p->child[i];
if (!p->isWord)
{
return false;
}
}
//如果是加入了单词则需要判断是不是被标记为isword
//这里是找是不是前缀因此不需要标记isword
return true;
}
};
class Solution
{
public:
string longestWord(vector<string> &words)
{
std::sort(words.begin(), words.end(),
[](const string &w1, const string &w2) {
if (w1.length() != w2.length())
return w1.length() > w2.length();
return w1 < w2;
});
Trie trie;
for (const string &word : words)
{
trie.insert(word);
}
for (const string &word : words)
{
if (trie.startsWith(word))
{
return word;
}
}
return "";
}
};