Strings from an array which are not prefix of any other string
Given an array arr[] of strings, the task is to print the strings from the array which are not prefix of any other string from the same array.
Examples:
Input: arr[] = {“apple”, “app”, “there”, “the”, “like”}
Output:
apple
like
there
Here “app” is a prefix of “apple”
Hence, it is not printed and
“the” is a prefix of “there”
Input: arr[] = {“a”, “aa”, “aaa”, “aaaa”}
Output:
aaaa
Naive approach: For every string of the array, we check if it is prefix of any other string. If it is then don’t display it.
Efficient approach: We pick strings from array one by one and insert it into Trie. Then there are two cases for the insertion of the string:
- While inserting if we found that the picked string is a prefix of an already inserted string then we don’t insert this string into the Trie.
- If a prefix is inserted first into the Trie and afterwards we find that the string is a prefix of some word then we simply make isEndOfWord = false for that particular node.
After constructing the Trie, we traverse it and display all the words in the Trie.
Below is the implementation of the above approach:
- C++
- Java
- Python3
- C#
- Javascript
C++
// C++ implementation of the approach #include <bits/stdc++.h> using namespace std; const int ALPHABET_SIZE = 26; // Trie node struct TrieNode { struct TrieNode* children[ALPHABET_SIZE]; // isEndOfWord is true if the node represents // end of a word bool isEndOfWord; }; // Returns new trie node (initialized to NULLs) struct TrieNode* getNode( void ) { struct TrieNode* pNode = new TrieNode; pNode->isEndOfWord = false ; for ( int i = 0; i < ALPHABET_SIZE; i++) pNode->children[i] = NULL; return pNode; } // Function to insert a string into trie void insert( struct TrieNode* root, string key) { struct TrieNode* pCrawl = root; for ( int i = 0; i < key.length(); i++) { int index = key[i] - 'a' ; if (!pCrawl->children[index]) pCrawl->children[index] = getNode(); // While inerting a word make // each isEndOfWord as false pCrawl->isEndOfWord = false ; pCrawl = pCrawl->children[index]; } int i; // Check if this word is prefix of // some already inserted word // If it is then don't insert this word for (i = 0; i < 26; i++) { if (pCrawl->children[i]) { break ; } } // If present word is not prefix of // any other word then insert it if (i == 26) { pCrawl->isEndOfWord = true ; } } // Function to display words in Trie void display( struct TrieNode* root, char str[], int level) { // If node is leaf node, it indicates end // of string, so a null character is added // and string is displayed if (root->isEndOfWord) { str[level] = '\0' ; cout << str << endl; } int i; for (i = 0; i < ALPHABET_SIZE; i++) { // If NON NULL child is found // add parent key to str and // call the display function recursively // for child node if (root->children[i]) { str[level] = i + 'a' ; display(root->children[i], str, level + 1); } } } // Driver code int main() { string keys[] = { "apple" , "app" , "there" , "the" , "like" }; int n = sizeof (keys) / sizeof (string); struct TrieNode* root = getNode(); // Construct trie for ( int i = 0; i < n; i++) insert(root, keys[i]); char str[100]; display(root, str, 0); return 0; } |
Java
Python3
C#
Javascript
apple like there
Time Complexity : Inserting all the words in the trie takes O(MN) time where-
N = Number of strings
M = Length of the largest string
Auxiliary Space : To store all the strings we need to allocate O(26*M*N) ~ O(MN) space for the Trie.
Approach#2: Using Brute Force
In this approach, we will compare each string in the array with every other string to check whether it is a prefix of any other string. If a string is not a prefix of any other string, we will add it to the output list.
Algorithm
1. Initialize an empty list output to hold the non-prefix strings.
2. Loop through each string in the input array arr.
3. For each string, check if it is a prefix of any other string in the array by looping through the array again and using the startswith() method.
4. If the string is not a prefix of any other string, add it to the output list.
5. Once all strings in the input array have been checked, return the output list containing only the non-prefix strings.
- C++
- Java
- Python3
- C#
- Javascript
C++
#include <iostream> #include <vector> #include <string> using namespace std; // Function to find non-prefix strings vector<string> nonPrefixStrings( const vector<string>& arr) { vector<string> output; for ( int i = 0; i < arr.size(); i++) { bool isPrefix = false ; for ( int j = 0; j < arr.size(); j++) { if (i != j && arr[j].find(arr[i]) == 0) { // Check if arr[j] starts with arr[i] isPrefix = true ; break ; } } if (!isPrefix) { output.push_back(arr[i]); } } return output; } int main() { vector<string> arr = { "apple" , "app" , "there" , "the" , "like" }; vector<string> result = nonPrefixStrings(arr); //cout << "Non-prefix strings in the array: "; for ( const string& str : result) { cout << str << " " ; } return 0; } |
Java
Python3
C#
Javascript
['apple', 'there', 'like']
Time complexity: O(n^2), where n is length of array
Auxiliary Space: O(n), where n is length of array