Open In App

Sorting array of strings (or words) using Trie | Set-2 (Handling Duplicates)

Last Updated : 06 Feb, 2023
Comments
Improve
Suggest changes
Like Article
Like
Report

Given an array of strings, print them in alphabetical (dictionary) order. If there are duplicates in input array, we need to print all the occurrences.
Examples: 
 

Input : arr[] = { "abc", "xyz", "abcd", "bcd", "abc" }
Output : abc abc abcd bcd xyz

Input : arr[] = { "geeks", "for", "geeks", "a", "portal", 
                  "to", "learn" }
Output : a for geeks geeks learn portal to


 


Prerequisite: Trie | (Insert and Search). 
Approach: In the previous post array of strings is being sorted, printing only single occurrence of duplicate strings. In this post all occurrences of duplicate strings are printed in lexicographic order. To print the strings in alphabetical order we have to first insert them in the trie and then perform preorder traversal to print in alphabetical order. The nodes of trie contain an index[] array which stores the index position of all the strings of arr[] ending at that node. Except for trie's leaf node all the other nodes have size 0 for the index[] array.
Below is the implementation of the above approach.
 

C++
// C++ implementation to sort an array
// of strings using Trie
#include <bits/stdc++.h>
using namespace std;

const int MAX_CHAR = 26;

struct Trie {

    // 'index' vectors size is greater than 
    // 0 when node/ is a leaf node, otherwise
    // size is 0;
    vector<int> index;

    Trie* child[MAX_CHAR];

    /*to make new trie*/
    Trie()
    {
        // initializing fields
        for (int i = 0; i < MAX_CHAR; i++)
            child[i] = NULL;
    }
};

// function to insert a string in trie
void insert(Trie* root, string str, int index)
{
    Trie* node = root;

    for (int i = 0; i < str.size(); i++) {

        // taking ascii value to find index of
        // child node
        char ind = str[i] - 'a';

        // making a new path if not already
        if (!node->child[ind])
            node->child[ind] = new Trie();

        // go to next node
        node = node->child[ind];
    }

    // Mark leaf (end of string) and store
    // index of 'str' in index[]
    (node->index).push_back(index);
}

// function for preorder traversal of trie
void preorder(Trie* node, string arr[])
{
    // if node is empty
    if (node == NULL)
        return;

    for (int i = 0; i < MAX_CHAR; i++) {
        if (node->child[i] != NULL) {

            // if leaf node then print all the strings
            // for (node->child[i]->index).size() > 0)
            for (int j = 0; j < (node->child[i]->index).size(); j++)
                cout << arr[node->child[i]->index[j]] << " ";

            preorder(node->child[i], arr);
        }
    }
}

// function to sort an array
// of strings using Trie
void printSorted(string arr[], int n)
{
    Trie* root = new Trie();

    // insert all strings of dictionary into trie
    for (int i = 0; i < n; i++)
        insert(root, arr[i], i);

    // print strings in lexicographic order
    preorder(root, arr);
}

// Driver program to test above
int main()
{
    string arr[] = { "abc", "xyz", "abcd", "bcd", "abc" };
    int n = sizeof(arr) / sizeof(arr[0]);
    printSorted(arr, n);
    return 0;
}
Java C# Python3 JavaScript

Output:  

abc abc abcd bcd xyz


Time Complexity: Worst case occurs when every string is starting with a different character. In that case, it will visit all the nodes of each character of each string. So worst-case time complexity will be the sum of the length of every string i.e. O(|S1| + |S2| + |S3| + ... + |Sn|) where |S| is the length of the string.

Auxiliary Space: O((|S1| + |S2| + |S3| + ... + |Sn|)*MAX_CHAR)
 


Next Article

Similar Reads