Strings from an array which are not prefix of any other string
Last Updated :
09 Nov, 2023
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++
// 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
// Java implementation of the approach
import java.util.Arrays;
class GFG
{
static final int ALPHABET_SIZE = 26;
// Trie node
static class TrieNode
{
TrieNode[] children;
// isEndOfWord is true if the node represents
// end of a word
boolean isEndOfWord;
TrieNode()
{
this.children = new TrieNode[ALPHABET_SIZE];
}
}
// Returns new trie node (initialized to NULLs)
static TrieNode getNode()
{
TrieNode pNode = new TrieNode();
pNode.isEndOfWord = false;
Arrays.fill(pNode.children, null);
return pNode;
}
// Function to insert a String into trie
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();
// 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] != null)
{
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
static void display(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';
System.out.println(str);
}
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] != null)
{
str[level] = (char) (i + 'a');
display(root.children[i], str, level + 1);
}
}
}
// Driver code
public static void main(String[] args)
{
String keys[] = { "apple", "app", "there", "the", "like" };
int n = keys.length;
TrieNode root = getNode();
// Conclass trie
for (int i = 0; i < n; i++)
insert(root, keys[i]);
char[] str = new char[100];
display(root, str, 0);
}
}
// This code is contributed by sanjeev2552
Python3
# Python3 implementation of the approach
ALPHABET_SIZE = 26
count = 0
# Trie node
class TrieNode:
global ALPHABET_SIZE
# Constructor to set the data of
# the newly created tree node
def __init__(self):
self.isEndOfWord = False
self.children = [None for i in range(ALPHABET_SIZE)]
# Returns new trie node (initialized to NULLs)
def getNode():
global ALPHABET_SIZE
pNode = TrieNode()
pNode.isEndOfWord = False
for i in range(ALPHABET_SIZE):
pNode.children[i] = None
return pNode
# Function to insert a String into trie
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()
# While inerting a word make
# each isEndOfWord as false
pCrawl.isEndOfWord = False
pCrawl = pCrawl.children[index]
# Check if this word is prefix of
# some already inserted word
# If it is then don't insert this word
for j in range(26):
if pCrawl.children[j] != None:
break
# If present word is not prefix of
# any other word then insert it
if j == 26:
pCrawl.isEndOfWord = True
# Function to display words in Trie
def display(root, Str, level):
global ALPHABET_SIZE, count
# If node is leaf node, it indicates end
# of String, so a null character is added
# and String is displayed
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 NON NULL child is found
# add parent key to str and
# call the display function recursively
# for child node
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()
# Conclass trie
for i in range(n):
insert(root, keys[i])
Str = ['' for i in range(100)]
display(root, Str, 0)
# This code is contributed by rameshtravel07.
C#
// C# implementation of the approach
using System;
class GFG {
static int ALPHABET_SIZE = 26;
// Trie node
class TrieNode {
public bool isEndOfWord;
public TrieNode[] children;
public TrieNode()
{
isEndOfWord = false;
children = new TrieNode[ALPHABET_SIZE];
}
}
// Returns new trie node (initialized to NULLs)
static TrieNode getNode()
{
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
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();
// While inerting a word make
// each isEndOfWord as false
pCrawl.isEndOfWord = false;
pCrawl = pCrawl.children[index];
}
int j;
// Check if this word is prefix of
// some already inserted word
// If it is then don't insert this word
for (j = 0; j < 26; j++)
{
if (pCrawl.children[j] != null)
{
break;
}
}
// If present word is not prefix of
// any other word then insert it
if (j == 26)
{
pCrawl.isEndOfWord = true;
}
}
// Function to display words in Trie
static void display(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';
Console.WriteLine(str);
}
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] != 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();
// Conclass trie
for (int i = 0; i < n; i++)
insert(root, keys[i]);
char[] str = new char[100];
display(root, str, 0);
}
}
// This code is contributed by mukesh07.
JavaScript
<script>
// Javascript implementation of the approach
let ALPHABET_SIZE = 26;
// Trie node
class TrieNode
{
constructor() {
this.isEndOfWord = false;
this.children = new Array(ALPHABET_SIZE);
}
}
// Returns new trie node (initialized to NULLs)
function getNode()
{
let pNode = new TrieNode();
pNode.isEndOfWord = false;
for(let i = 0; i < ALPHABET_SIZE; i++)
{
pNode.children[i] = null;
}
return pNode;
}
// Function to insert a String into trie
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();
// While inerting a word make
// each isEndOfWord as false
pCrawl.isEndOfWord = false;
pCrawl = pCrawl.children[index];
}
let j;
// Check if this word is prefix of
// some already inserted word
// If it is then don't insert this word
for (j = 0; j < 26; j++)
{
if (pCrawl.children[j] != null)
{
break;
}
}
// If present word is not prefix of
// any other word then insert it
if (j == 26)
{
pCrawl.isEndOfWord = true;
}
}
// Function to display words in Trie
function display(root, str, 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';
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();
// Conclass trie
for (let i = 0; i < n; i++)
insert(root, keys[i]);
let str = new Array(100);
display(root, str, 0);
// This code is contributed by divyesh072019.
</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;
// 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
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
{
// Function to find non-prefix strings
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]))
{
// Check if arr[j] starts with 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
// Javascript code addition
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));
// The code is contributed by Arusi Goel.
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
Similar Reads
Search in an array of strings where non-empty strings are sorted
Given an array of strings. The array has both empty and non-empty strings. All non-empty strings are in sorted order. Empty strings can be present anywhere between non-empty strings. Examples: Input : arr[] = {"for", "", "", "", "geeks", "ide", "", "practice", "" , "", "quiz", "", ""}; str = "quiz"
9 min read
Frequency of a string in an array of strings
You are given a collection of strings and a list of queries. For every query there is a string given. We need to print the number of times the given string occurs in the collection of strings. Examples: Input : arr[] = {wer, wer, tyu, oio, tyu} q[] = {wer, tyu, uio}Output : 2 2 0Explanation : q[0] a
15 min read
Longest string in an array which matches with prefix of the given string
Given an array of strings arr[] and Q queries where each query consists of a string str, the task is to find the longest string in the array that matches with prefix of the given string str i.e. the string must be prefix of str. Examples: Input: arr[] = {"GeeksForGeeks", "GeeksForGeeksd", "Arnab", "
8 min read
Longest string which is prefix string of at least two strings
Given a set of strings of the same length, we need to find the length of the longest string, which is a prefix string of at least two strings. Examples: Input: ["abcde", "abcsd", "bcsdf", "abcda", "abced"] Output: 4 Explanation: Longest prefix string is "abcd". Input: ["pqrstq", "pwxyza", "abcdef",
6 min read
Generate a string which differs by only a single character from all given strings
Given an array of strings str[] of length N, consisting of strings of the same length, the task is to find the string which only differs by a single character from all the given strings. If no such string can be generated, print -1. In case of multiple possible answers, print any of them. Example: I
15 min read
Search strings with the help of given pattern in an Array of strings
Prerequisite: Trie | (Insert and Search) Given an array of strings words[] and a partial string str, the task is to find the strings of the given form str from the given array of string. A partial string is a string with some missing characters. For Example: "..ta", is a string of length 4 ending wi
12 min read
Removing string that is an anagram of an earlier string
Given an array arr of strings, the task is to remove the strings that are an anagram of an earlier string, then print the remaining array in sorted order. Examples: Input: arr[] = { "geeks", "keegs", "code", "doce" }, N = 4 Output: ["code", "geeks"] Explanation: "geeks" and "keegs" are anagrams, so
7 min read
Count of strings that does not contain any character of a given string
Given an array arr containing N strings and a string str, the task is to find the number of strings that do not contain any character of string str. Examples: Input: arr[] = {"abcd", "hijk", "xyz", "ayt"}, str="apple"Output: 2Explanation: "hijk" and "xyz" are the strings that do not contain any char
8 min read
All possible strings of any length that can be formed from a given string
Given a string of distinct characters, print all possible strings of any length that can be formed from given string characters. Examples: Input: abcOutput: a b c abc ab ac bc bac bca cb ca ba cab cba acbInput: abcdOutput: a b ab ba c ac ca bc cb abc acb bac bca cab cba d ad da bd db abd adb bad bda
10 min read
Remove longest prefix of the String which has duplicate substring
Given a string S of length N, the task is to remove the longest prefix of the string which has at least one duplicate substring present in S. Note: The duplicate substring cannot be the prefix itself Examples: Input: S = "GeeksforGeeks"Output: "forGeeks"Explanation: The longest substring which has a
5 min read