# Longest Word In Dictionary Problem

## Description

LeetCode Problem 720. 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.

All the strings in the input will only contain lowercase letters.

Example:

``````1
2
3
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".
``````

## Solution

#### Brute Force Approach

A simple solution is to use the `brute force` approach.

We loop through every word in the dictionary. For each word, we loop through every prefix of the world and check whether that prefix of the word exists in the dictonary. Finally, we return the longest word that every prefix of the word exists in the dictionary.

The time complexity of this approach is O(n2m), where n is the length of the dictionary and m is the maximum length of the word in the dictionary. The space complexity is O(1).

#### Trie and Depth First Search Approach

We can use the data structure `trie` to store the dictionary and use `depth first search` to find the longest possible answer. Using the `trie` data structure can help us reduce the time complexity.

In every trie node, we use an array of length 26 to store possible next trie node, and a flag to indicate whether the trie node is the last letter of a word in the dictionary.

Suppose we have a dictionary of words like this, words = [“a”, “banana”, “app”, “appl”, “ap”, “apply”, “apple”, “bar”]. The trie structure we build looks like the following. If the node is an end of a word, there is a * next to it.

``````1
2
3
4
5
6
7
8
9
10
11
a*   b
|    |
p*   a
|    | \
p*   n  r*
|    |
l*   a
|    |
e*   n
|
a*
``````

After we build the trie, we can use depth first search to find the longest word that every letter in that word is an end of a word (marked by * in the above) in the dictionary.

The time complexity can be reduced to O(sum(mi)), where mi is the length of a word in the dictionary. The space complexity is O(sum(mi)).

## Sample C++ Code

This is a C++ implementation of the trie and depth first search approach.

``````1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

struct TrieNode {
TrieNode* arr;
bool is_end;
TrieNode() {
for (int i = 0; i < 26; i ++) arr[i] = NULL;
is_end = false;
}
};

void insert(TrieNode* root, string key) {
TrieNode* curr = root;
for (int i = 0; i < key.size(); i ++) {
int idx = key[i] - 'a';
if (curr->arr[idx] == NULL)
curr->arr[idx] = new TrieNode();
curr = curr->arr[idx];
}
curr->is_end = true;
}

void dfs(TrieNode* root, string key, string& ans) {
if (root == NULL) return;
for (int i = 0; i < 26; i ++) {
if (root->arr[i] != NULL) {
if (root->arr[i]->is_end == true) {
key += (char)(i) + 'a';
if (key.size() > ans.size())
ans = key;
else if (key.size() == ans.size()) {
if (key < ans)
ans = key;
}
dfs(root->arr[i], key, ans);
key.pop_back();
}
}
}
}

string longestWord(vector<string>& words) {
TrieNode* root = new TrieNode();
for (int i = 0; i < words.size(); i ++)
insert(root, words[i]);
string ans;
dfs(root, "", ans);
return ans;
}

int main() {
vector<string> words = {"w","wo","wor","worl", "world"};
cout << longestWord(words) << endl;
}
``````