Problem Statement
Given a list of words ‘WORDLIST’, find the longest word such that all the possible prefixes of that word are present in ‘WORDLIST’.
If more than one word meets the criteria, return the word with the smallest lexicographical order. You can return an empty string if no such word is possible for the input.
Input
Enter number of words: 6
w wo wor wow worm work
Output
Longest word in dictionary: work
Explanation
Both “worm” and “work” are the longest words present in ‘WORDLIST’ that have all possible prefixes in the list. As “work” is lexicographically smaller than “worm”, “work” is returned as an answer.
Method 1: Using HashSet
Store all the words in a HashSet. HashSet offers O(1) lookup time. Once all the words are stored in HashSet, we can perform a linear traversal through the ‘WORDLIST’.
For each word, all the possible prefixes can be generated. If all the prefixes of the current word are present in the ‘WORDLIST’ and it is the longest yet discovered, we can set it as the answer. If an answer with equal length is already present, check the lexicographical order between the answer and the current word.
An optimized approach HashSetHashSete to sort the ‘WORDLIST’ first by length and lexicographic order of words.
Algorithm
- Sort the words according to their length and lexicographical order.
- Create a ‘HASH_SET’ to store the 'WORDLIST' for faster lookup.
-
For ‘CURRENT_STRING’ from beginning to end of the ‘WORDLIST’, do:
- Insert ‘CURRENT_STRING’ into ‘HASH_SET’.
-
For ‘CURRENT_STRING’ from beginning to end of the ‘WORDLIST’, do:
- Initialize ‘CURRENT_PREFIX’ as an empty string.
- Initialize the ‘ALL_PREFIXES_PRESENT’ boolean with true.
-
For ‘CURRENT_CHAR’ from beginning to end of the ‘CURRENT_STRING’, do:
- Add ‘CURRENT_CHAR’ to ‘CURRENT_PREFIX’.
-
If ‘CURRENT_PREFIX’ is not present in ‘HASH_SET’, then:
- Set ‘ALL_PREFIXES_PRESENT’ = false.
- Break the loop.
-
If ‘ALL_PREFIXES_PRESENT’ is true, then:
- Return ‘ALL_PREFIXES_PRESENT’.
- Return an empty string.
Program
#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_set>
using namespace std;
bool comparator(string &a, string &b)
{
// If both strings have equal length, return the one which comes first in lexicographical order.
if (a.length() == b.length())
return a < b;
// If string lengths are not equal return the longest.
return a.length() > b.length();
}
string longestWord(vector<string> &wordlist)
{
// Sorting the words according to their length and lexicographical order.
sort(wordlist.begin(), wordlist.end(), comparator);
// Creating a hashset to store the 'WORDLIST' for faster lookup.
unordered_set<string> hashSet;
// Inserting the words from 'WORDLIST' into hashSet.
for (string currentString : wordlist)
hashSet.insert(currentString);
// Considering each word from the wordlist to check all possible prefixes in the hashSet.
for (string currentString : wordlist)
{
// Creating temporary storage to push letters from 'CURRENT_STRING' one by one.
string currentPrefix = "";
// Boolean variable to represent if there is any prefix which is not present in the 'WORDLIST'.
bool allPrefixesPresent = true;
// Taking characters sequentially to add them for creating prefixes.
for (char currentChar : currentString)
{
currentPrefix.push_back(currentChar);
// If current prefix is not present in the 'WORDLIST', the 'CURRENT_STRING' can not be considered as answer.
if (hashSet.find(currentPrefix) == hashSet.end())
{
allPrefixesPresent = false;
break;
}
}
// Checking if all the prefixes present for the 'CURRENT_STRING'.
// If yes, this is our final answer.
if (allPrefixesPresent)
return currentString;
}
// Returning an empty string in case no word meets the criteria.
return "";
}
int main()
{
int numWords;
cout << "Enter number of words: ";
cin >> numWords;
vector<string> wordlist(numWords);
for (int i = 0; i < numWords; i++)
{
cin >> wordlist[i];
}
cout << "Longest word in dictionary: ";
cout << longestWord(wordlist);
}
Input
Enter number of words: 6
w wo wor wow worm work
Output
Longest word in dictionary: work
Complexity Analysis
Time Complexity: Checking each prefix requires a linear-time operation. For a word with the length ‘W’, the maximum length of a prefix is ‘W’. The time complexity to check the maximum length prefix in the set is O(W). For the word ‘W’ in the ‘WORDLIST’, all the possible prefixes are checked. So, the time complexity to check all prefixes of a word is O(W2). To check prefixes of all the words, the time complexity is O(∑Wi2), where Wi represents each word from the ‘WORDLIST’.
Space Complexity: To create all prefixes of a word, extra space is required. So, the space complexity is O(∑Wi2), where Wi represents each word from the ‘WORDLIST’.