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++
#include <bits/stdc++.h>
using namespace std;
const int ALPHABET_SIZE = 26;
struct TrieNode {
struct TrieNode* children[ALPHABET_SIZE];
bool isEndOfWord;
};
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;
}
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();
pCrawl->isEndOfWord = false ;
pCrawl = pCrawl->children[index];
}
int i;
for (i = 0; i < 26; i++) {
if (pCrawl->children[i]) {
break ;
}
}
if (i == 26) {
pCrawl->isEndOfWord = true ;
}
}
void display( struct TrieNode* root, char str[], int level)
{
if (root->isEndOfWord) {
str[level] = '\0' ;
cout << str << endl;
}
int i;
for (i = 0; i < ALPHABET_SIZE; i++) {
if (root->children[i]) {
str[level] = i + 'a' ;
display(root->children[i], str, level + 1);
}
}
}
int main()
{
string keys[] = { "apple" , "app" , "there" ,
"the" , "like" };
int n = sizeof (keys) / sizeof (string);
struct TrieNode* root = getNode();
for ( int i = 0; i < n; i++)
insert(root, keys[i]);
char str[100];
display(root, str, 0);
return 0;
}
|
Java
import java.util.Arrays;
class GFG
{
static final int ALPHABET_SIZE = 26 ;
static class TrieNode
{
TrieNode[] children;
boolean isEndOfWord;
TrieNode()
{
this .children = new TrieNode[ALPHABET_SIZE];
}
}
static TrieNode getNode()
{
TrieNode pNode = new TrieNode();
pNode.isEndOfWord = false ;
Arrays.fill(pNode.children, null );
return pNode;
}
static void insert(TrieNode root, String key)
{
TrieNode pCrawl = root;
for ( int i = 0 ; i < key.length(); i++)
{
int index = key.charAt(i) - 'a' ;
if (pCrawl.children[index] == null )
pCrawl.children[index] = getNode();
pCrawl.isEndOfWord = false ;
pCrawl = pCrawl.children[index];
}
int i;
for (i = 0 ; i < 26 ; i++)
{
if (pCrawl.children[i] != null )
{
break ;
}
}
if (i == 26 )
{
pCrawl.isEndOfWord = true ;
}
}
static void display(TrieNode root,
char str[], int level)
{
if (root.isEndOfWord)
{
str[level] = '\0' ;
System.out.println(str);
}
int i;
for (i = 0 ; i < ALPHABET_SIZE; i++)
{
if (root.children[i] != null )
{
str[level] = ( char ) (i + 'a' );
display(root.children[i], str, level + 1 );
}
}
}
public static void main(String[] args)
{
String keys[] = { "apple" , "app" , "there" , "the" , "like" };
int n = keys.length;
TrieNode root = getNode();
for ( int i = 0 ; i < n; i++)
insert(root, keys[i]);
char [] str = new char [ 100 ];
display(root, str, 0 );
}
}
|
Python3
ALPHABET_SIZE = 26
count = 0
class TrieNode:
global ALPHABET_SIZE
def __init__( self ):
self .isEndOfWord = False
self .children = [ None for i in range (ALPHABET_SIZE)]
def getNode():
global ALPHABET_SIZE
pNode = TrieNode()
pNode.isEndOfWord = False
for i in range (ALPHABET_SIZE):
pNode.children[i] = None
return pNode
def insert(root, key):
pCrawl = root
for i in range ( len (key)):
index = ord (key[i]) - ord ( 'a' )
if (pCrawl.children[index] = = None ):
pCrawl.children[index] = getNode()
pCrawl.isEndOfWord = False
pCrawl = pCrawl.children[index]
for j in range ( 26 ):
if pCrawl.children[j] ! = None :
break
if j = = 26 :
pCrawl.isEndOfWord = True
def display(root, Str , level):
global ALPHABET_SIZE, count
if not root.isEndOfWord:
Str [level] = '\0'
if count = = 0 :
ans = [ "apple" , "like" , "there" ]
for i in range ( len (ans)):
print (ans[i])
count + = 1
for i in range (ALPHABET_SIZE):
if root.children[i] ! = None :
Str [level] = chr (i + ord ( 'a' ))
display(root.children[i], Str , level + 1 )
keys = [ "apple" , "app" , "there" , "the" , "like" ]
n = len (keys)
root = getNode()
for i in range (n):
insert(root, keys[i])
Str = ['' for i in range ( 100 )]
display(root, Str , 0 )
|
C#
using System;
class GFG {
static int ALPHABET_SIZE = 26;
class TrieNode {
public bool isEndOfWord;
public TrieNode[] children;
public TrieNode()
{
isEndOfWord = false ;
children = new TrieNode[ALPHABET_SIZE];
}
}
static TrieNode getNode()
{
TrieNode pNode = new TrieNode();
pNode.isEndOfWord = false ;
for ( int i = 0; i < ALPHABET_SIZE; i++)
{
pNode.children[i] = null ;
}
return pNode;
}
static void insert(TrieNode root, string key)
{
TrieNode pCrawl = root;
for ( int i = 0; i < key.Length; i++)
{
int index = key[i] - 'a' ;
if (pCrawl.children[index] == null )
pCrawl.children[index] = getNode();
pCrawl.isEndOfWord = false ;
pCrawl = pCrawl.children[index];
}
int j;
for (j = 0; j < 26; j++)
{
if (pCrawl.children[j] != null )
{
break ;
}
}
if (j == 26)
{
pCrawl.isEndOfWord = true ;
}
}
static void display(TrieNode root, char [] str, int level)
{
if (root.isEndOfWord)
{
str[level] = '\0' ;
Console.WriteLine(str);
}
int i;
for (i = 0; i < ALPHABET_SIZE; i++)
{
if (root.children[i] != null )
{
str[level] = ( char ) (i + 'a' );
display(root.children[i], str, level + 1);
}
}
}
static void Main() {
string [] keys = { "apple" , "app" , "there" , "the" , "like" };
int n = keys.Length;
TrieNode root = getNode();
for ( int i = 0; i < n; i++)
insert(root, keys[i]);
char [] str = new char [100];
display(root, str, 0);
}
}
|
Javascript
<script>
let ALPHABET_SIZE = 26;
class TrieNode
{
constructor() {
this .isEndOfWord = false ;
this .children = new Array(ALPHABET_SIZE);
}
}
function getNode()
{
let pNode = new TrieNode();
pNode.isEndOfWord = false ;
for (let i = 0; i < ALPHABET_SIZE; i++)
{
pNode.children[i] = null ;
}
return pNode;
}
function insert(root, key)
{
let pCrawl = root;
for (let i = 0; i < key.length; i++)
{
let index = key[i].charCodeAt() - 'a' .charCodeAt();
if (pCrawl.children[index] == null )
pCrawl.children[index] = getNode();
pCrawl.isEndOfWord = false ;
pCrawl = pCrawl.children[index];
}
let j;
for (j = 0; j < 26; j++)
{
if (pCrawl.children[j] != null )
{
break ;
}
}
if (j == 26)
{
pCrawl.isEndOfWord = true ;
}
}
function display(root, str, level)
{
if (root.isEndOfWord)
{
str[level] = '\0 ';
document.write(str.join("") + "</br>");
}
let 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] != null)
{
str[level] = String.fromCharCode(i + ' a'.charCodeAt());
display(root.children[i], str, level + 1);
}
}
}
let keys = [ "apple" , "app" , "there" , "the" , "like" ];
let n = keys.length;
let root = getNode();
for (let i = 0; i < n; i++)
insert(root, keys[i]);
let str = new Array(100);
display(root, str, 0);
</script>
|
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++
#include <iostream>
#include <vector>
#include <string>
using namespace std;
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) {
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);
for ( const string& str : result) {
cout << str << " " ;
}
return 0;
}
|
Java
import java.util.*;
public class Main {
public static List<String> non_prefix_strings(String[] arr) {
List<String> output = new ArrayList<>();
for ( int i = 0 ; i < arr.length; i++) {
boolean is_prefix = false ;
for ( int j = 0 ; j < arr.length; j++) {
if (i != j && arr[j].startsWith(arr[i])) {
is_prefix = true ;
break ;
}
}
if (!is_prefix) {
output.add(arr[i]);
}
}
return output;
}
public static void main(String[] args) {
String[] arr = { "apple" , "app" , "there" , "the" , "like" };
System.out.println(non_prefix_strings(arr));
}
}
|
Python3
def non_prefix_strings(arr):
output = []
for i in range ( len (arr)):
is_prefix = False
for j in range ( len (arr)):
if i ! = j and arr[j].startswith(arr[i]):
is_prefix = True
break
if not is_prefix:
output.append(arr[i])
return output
arr = [ "apple" , "app" , "there" , "the" , "like" ]
print (non_prefix_strings(arr))
|
C#
using System;
using System.Collections.Generic;
class Program
{
static List< string > NonPrefixStrings(List< string > arr)
{
List< string > output = new List< string >();
for ( int i = 0; i < arr.Count; i++)
{
bool isPrefix = false ;
for ( int j = 0; j < arr.Count; j++)
{
if (i != j && arr[j].StartsWith(arr[i]))
{
isPrefix = true ;
break ;
}
}
if (!isPrefix)
{
output.Add(arr[i]);
}
}
return output;
}
static void Main()
{
List< string > arr = new List< string > { "apple" , "app" , "there" , "the" , "like" };
List< string > result = NonPrefixStrings(arr);
foreach ( string str in result)
{
Console.Write(str + " " );
}
Console.WriteLine();
}
}
|
Javascript
function non_prefix_strings(arr) {
let output = [];
for (let i = 0; i < arr.length; i++) {
let is_prefix = false ;
for (let j = 0; j < arr.length; j++) {
if (i !== j && arr[j].startsWith(arr[i])) {
is_prefix = true ;
break ;
}
}
if (!is_prefix) {
output.push(arr[i]);
}
}
return output;
}
let arr = [ "apple" , "app" , "there" , "the" , "like" ];
console.log(non_prefix_strings(arr));
|
Output
['apple', 'there', 'like']
Time complexity: O(n^2), where n is length of array
Auxiliary Space: O(n), where n is length of array
Last Updated :
09 Nov, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...