给出一个字符串数组words
组成的一本英语词典。从中找出最长的一个单词,该单词是由words
词典中其他单词逐步添加一个字母组成。若其中有多个可行的答案,则返回答案中字典序最小的单词。
若无答案,则返回空字符串。
示例 1:
输入:
words = ["w","wo","wor","worl", "world"]
输出: "world"
解释:
单词"world"可由"w", "wo", "wor", 和 "worl"添加一个字母组成。
示例 2:
输入:
words = ["a", "banana", "app", "appl", "ap", "apply", "apple"]
输出: "apple"
解释:
"apply"和"apple"都能由词典中的单词组成。但是"apple"得字典序小于"apply"。
注意:
- 所有输入的字符串都只包含小写字母。
words
数组长度范围为[1,1000]
。words[i]
的长度范围为[1,30]
。
字典树
题目要求找最长的单词,并且这个单词必须由其他单词逐一添加字母构成,也就是这个最长单词在字典树边中每个点都必须是某个单词的终点
class Solution
{
private:
static const int maxn = 10000;//设大点,也不能太大,太大会爆栈
int tot = 1, trie[maxn][26], cnt[maxn];
int maxlen = 0;
void insert(string str)
{
int p = 1;
for (char c : str)
{
int ch = c - 'a';
if (trie[p][ch] == 0)
trie[p][ch] = ++tot;
p = trie[p][ch];
}
++cnt[p];//标记终点
}
bool check(string str)
{
int p = 1, times = 0;
for (char c : str)
{
p = trie[p][c - 'a'];
//遇到终点,组不成单词 || 在路径中,该点不是通过逐一添加单词组成的
if (p == 0 || cnt[p] == 0)
return false;
++times;//累加长度
}
return times > maxlen ? maxlen = times : 0;//更新答案
}
public:
string longestWord(vector<string> &words)
{
sort(words.begin(), words.end());//排序保证长度相同下字典序最小
for (string str : words)
insert(str);
string ans;
for (string str : words)
if (check(str))//可以组成更新答案
ans = str;
return ans;
}
};