题目来源
题目描述
题目解析
set
- 对数组排序,再利用Set对字母存储,小的单词一定包含在后面大的单词里面。后面只需要取前缀相同的
- 对字母排序后,第一个单词一定是共有的,后面只需在此基础上添加
class Solution {
public:
string longestWord(vector<string>& words) {
//1、先排序
std::sort(words.begin(), words.end());
//2、建立set
std::string ans;
std::set<std::string> set;
for(auto &word : words){
//提取当前字符串的前n-1个字符,如果在set中找得到。也就是去除最后一个字符,发现其子串在之前出现过,说明当前字符是由前面的串插入一个字符合成的
if(word.length() == 1 ||set.count(word.substr(0, word.size() - 1))){
set.insert(word);
ans = word.size() > ans.size() ? word : ans;
}
}
return ans;
}
};
字典树
Trie,又称前缀树或字典树,是一棵有根树,其每个节点包含如下字段:
- 指向子节点的指针数组children。就本题而言,数组长度为26,即小写英文字母的数量。此时 c h i l d r e n [ 0 ] children[0] children[0] 对应小写字母 a, c h i l d r e n [ 1 ] children[1] children[1] 对应小写字母 b,…, c h i l d r e n [ 25 ] children[25] children[25] 对应小写字母 z。
- 布尔字段isEnd,表示该节点是否为字符串的结尾
插入字符串
我们从字典树的根开始,插入字符串。对于当前字符对应的子节点,有两种情况:
- 子节点存在。沿着指针移动到子节点,继续处理下一个字符
- 子节点不存在。创建一个新的子节点,记录在children数组的对应位置上,然后沿着指针移动到子节点,继续搜索下一个字符。
重复以上步骤,直到处理字符串的最后一个字符,然后将当前节点标记为字符串的结尾。
查找前缀
我们从字典树的根开始,查找前缀。对于当前字符对应的子节点,有两种情况:
- 子节点存在。沿着指针移动到子节点,继续搜索下一个字符。
- 子节点不存在。说明字典树中不包含该前缀,返回空指针。
重复以上步骤,直到返回空指针或搜索完前缀的最后一个字符。
若搜索到了前缀的末尾,就说明字典树中存在该前缀。此外,若前缀末尾对应节点的isEnd 为真,则说明字典树中存在该字符串。
思路
由于符合要求的单词的每个前缀都是符合要求的单词,因此可以使用字典树存储所有符合要求的单词。
- 创建字典树,遍历数组words并将每个单词插入字典树。
- 当所有的单词都插入字典树之后,将答案初始化为空字符串,再次遍历数组words,判断每个单词是否是符合要求的单词,更更新答案。
- 如果一个单词是符合要求的单词,则比较curr_word与ans_word,如果curr_word.size() > ans_word.size(),或者curr_word.size() == ans_word.size()且curr_word的字典序 < ans_word的字典序,则将答案更新为curr_word。
#include <iterator>
#include <deque>
#include <algorithm>
#include <iostream>
#include <functional>
#include <set>
using namespace std;
class Trie{
public:
Trie(){
this->children = std::vector<Trie *>(26, nullptr);
this->isEnd = false;
}
bool insert(const std::string &word){
Trie *node = this;
for(const auto & ch : word){
int idx = ch - 'a';
if(node->children[idx] == nullptr){
node->children[idx] = new Trie();
}
node = node->children[idx];
}
node->isEnd = true;
}
bool search(const std::string &word){
Trie *node = this;
for (const auto & ch : word) {
int idx = ch - 'a';
if(node->children[idx] == nullptr || node->children[idx]->isEnd == false){
return false;
}
node = node->children[idx];
}
return node != nullptr && node->isEnd;
}
private:
std::vector<Trie *> children;
bool isEnd;
};
class Solution {
public:
string longestWord(vector<string>& words) {
Trie trie;
for (const auto & word : words) {
trie.insert(word);
}
std::string longest ;
for (const auto & word : words) {
if(trie.search(word)){
if (word.size() > longest.size() || (word.size() == longest.size() && word < longest)) {
longest = word;
}
}
}
return longest;
}
};
int main(){
Solution a;
std::vector<std::string> vec {"a", "banana", "app", "appl", "ap", "apply", "apple"};
std::cout << a.longestWord(vec);
}