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

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:  
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.
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++ implementation of the approach#include <bits/stdc++.h>using namespace std; const int ALPHABET_SIZE = 26; // Trie nodestruct 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 trievoid 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 Trievoid 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 codeint 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 implementation of the approachimport 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 implementation of the approachALPHABET_SIZE = 26count = 0 # Trie nodeclass 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 triedef 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 Triedef 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 triefor 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# implementation of the approachusing 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.
<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>
apple
like
there
 
Time Complexity : Inserting all the words in the trie takes O(MN) time where-
N = Number of stringsM = Length of the largest stringAuxiliary Space : To store all the strings we need to allocate O(26*M*N) ~ O(MN) space for the Trie.
ManasChhabra2
sanjeev2552
mukesh07
divyesh072019
rameshtravel07
hasani
Trie
Advanced Data Structure
Recursion
Searching
Strings
Searching
Strings
Recursion
Trie
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.