#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
struct TrieNode {
TrieNode* children[26] = {nullptr};
bool isWord = false;
};
class Trie {
public:
TrieNode* root;
Trie() { root = new TrieNode(); }
void insert(const string& word) {
TrieNode* curr = root;
for (char c : word) {
int idx = c - 'a';
if (!curr->children[idx])
curr->children[idx] = new TrieNode();
curr = curr->children[idx];
}
curr->isWord = true;
}
void dfs(TrieNode* node, string& path, string& longest) {
if (!node->isWord && node != root) return; // only continue if prefix is word
if (path.length() > longest.length() ||
(path.length() == longest.length() && path < longest)) {
longest = path;
}
for (int i = 0; i < 26; i++) {
if (node->children[i]) {
path.push_back('a' + i);
dfs(node->children[i], path, longest);
path.pop_back();
}
}
}
};
string longestWord(vector<string>& words) {
Trie trie;
for (const string& w : words) {
trie.insert(w);
}
string longest = "";
string path = "";
trie.dfs(trie.root, path, longest);
return longest;
}
int main() {
vector<string> words = {"a", "app", "ap", "apply", "apple", "appl"};
cout << longestWord(words) << "\n";
return 0;
}
if (!curr->children[idx])
curr->children[idx] = new TrieNode();
create child node if missing to build trie path
curr = curr->children[idx];
advance current node to child for next letter
mark node as end of a valid word
if (!node->isWord && node != root) return;
stop DFS if prefix is not a word (except root)
if (path.length() > longest.length() || (path.length() == longest.length() && path < longest)) {
longest = path;
}
update longest word if current path is longer or lex smaller
for (int i = 0; i < 26; i++) {
if (node->children[i]) {
path.push_back('a' + i);
dfs(node->children[i], path, longest);
path.pop_back();
}
}
explore all children recursively to find longest valid word