Skip to content
Related Articles

Related Articles

Strings from an array which are not prefix of any other string

View Discussion
Improve Article
Save Article
  • Difficulty Level : Medium
  • Last Updated : 31 May, 2022

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: 
 

  1. 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.
  2. 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>

Output: 

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.


My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!