Related Articles

Substring Sort

• Last Updated : 05 Aug, 2021

Given n strings, we need to sort those strings such that every string is a substring of all strings after it. If not possible to sort, then print the same.
Examples:

Input : {"d", "zddsaaz", "ds", "ddsaa", "dds"}
Output :
d
ds
dds
ddsaa
zddsaaz

Input : {"geeks", "ee", "geeksforgeeks", "forgeeks", "ee"}
Output :
ee
ee
geeks
forgeeks
geeksforgeeks

Observation 1
If A substring of B
Then length of A <= length of B
Observation 2
If (A substring of B ) and (B substring of C)
Then A substring of C
Solution
Based on the two above observations, the solutions is as follows

1. Sort all the string from the shorter to the longer
2. Validate that each string is a substring of the following string

If we validate that each string is a substring of the following string then based on observation 2, each string is a substring of all the strings come after it.

Java

 // Java code to sort substringsimport java.util.Arrays;import java.util.Comparator; public class Demo {    public static void substringSort(String[] arr, int n)    {        // sort the given array from shorter string to longer        Arrays.sort(arr, new Comparator() {            public int compare(String s1, String s2)            {                return Integer.compare(s1.length(), s2.length());            }        });         // validate that each string is a substring of        // the following one'        for (int i = 0; i < n - 1; i++) {            if (!arr[i + 1].contains(arr[i])) {                 // the array can't be sorted                System.out.println("Cannot be sorted");                return;            }        }         // The array is valid and sorted        // print the strings in order        for (int i = 0; i < n - 1; i++) {            System.out.println(arr[i]);        }    }     public static void main(String[] args)    {        // Test 1        String[] arr1 = { "d", "zddsaaz", "ds", "ddsaa", "dds" };        substringSort(arr1, arr1.length);         // Test 2        String[] arr2 = { "for", "rof" };        substringSort(arr2, arr2.length);    }}
Output:
d
ds
dds
ddsaa
Cannot be sorted

Complexity
Time Complexity: O(n log n), where n is the number of strings.
Alternative approach
For better time complexity, we can use counting sort only if the maximum length of the strings is specified.
Suppose that ‘maxLen’ is the maximum length of the input strings. In this case, the solution is as follows:

1. Create array of length maxLen
2. Sort the input strings such that the string with length 1 is in the first place in the array
3. If there is two or more string has the same length they must be equal otherwise the strings cannot be sorted
4. Validate that each string is a substring of the next longer string

C++

 // C++ Program to sort substrings#include using namespace std; void substringSort(string arr[], int n, int maxLen){     int count[maxLen];    string sortedArr[maxLen];    for(int i = 0; i < maxLen; i++)    {        count[i] = 0;        sortedArr[i] = "";    }     // sort the input array    for (int i = 0; i < n; i++)    {         string s = arr[i];        int len = s.length();         if (count[len - 1] == 0)        {            sortedArr[len - 1] = s;            count[len - 1] = 1;        }        else if (sortedArr[len - 1] == s)        {             // repeated length should            // be the same string            count[len - 1]++;        }        else        {             // two different strings with the same            // length input array cannot be sorted            cout << "Cannot be sorted";            return;        }    }     // validate that each string is a    // substring of the following one    int index = 0;     // get first element    while (count[index] == 0)        index++;     int prev = index;    string prevString = sortedArr[prev];     index++;     for (; index < maxLen; index++)    {         if (count[index] != 0)        {            string current = sortedArr[index];            if (current.find(prevString) != string::npos)            {                prev = index;                prevString = current;            }            else            {                cout << "Cannot be sorted";                return;            }        }    }     // The array is valid and sorted    // print the strings in order    for (int i = 0; i < maxLen; i++)    {        string s = sortedArr[i];        for (int j = 0; j < count[i]; j++)        {            cout << s << endl;        }    }} // Driver codeint main(){    int maxLen = 100;      // Test 1    string arr1[] = { "d", "zddsaaz", "ds", "ddsaa",                                   "dds", "dds" };    substringSort(arr1, sizeof(arr1)/sizeof(arr1[0]), maxLen);     // Test 2    string arr2[] = { "for", "rof" };    substringSort(arr2, sizeof(arr2)/sizeof(arr2[0]), maxLen);     return 0;} // This code is contributed by rameshtravel07.

Java

 // Alternative code to sort substringsimport java.util.Arrays; public class Demo {     public static void substringSort(String[] arr, int n, int maxLen)    {         int count[] = new int[maxLen];        String[] sortedArr = new String[maxLen];         Arrays.fill(count, 0);        Arrays.fill(sortedArr, "");         // sort the input array        for (int i = 0; i < n; i++) {             String s = arr[i];            int len = s.length();             if (count[len - 1] == 0) {                sortedArr[len - 1] = s;                count[len - 1] = 1;            }            else if (sortedArr[len - 1].equals(s)) {                 // repeated length should be the same string                count[len - 1]++;            }            else {                 // two different strings with the same                // length input array cannot be sorted                System.out.println("Cannot be sorted");                return;            }        }         // validate that each string is a substring        // of the following one        int index = 0;         // get first element        while (count[index] == 0)            index++;         int prev = index;        String prevString = sortedArr[prev];         index++;         for (; index < maxLen; index++) {             if (count[index] != 0) {                String current = sortedArr[index];                if (current.contains(prevString)) {                    prev = index;                    prevString = current;                }                else {                    System.out.println("Cannot be sorted");                    return;                }            }        }         // The array is valid and sorted        // print the strings in order        for (int i = 0; i < maxLen; i++) {            String s = sortedArr[i];            for (int j = 0; j < count[i]; j++) {                System.out.println(s);            }        }    }     public static void main(String[] args)    {        int maxLen = 100;         // Test 1        String[] arr1 = { "d", "zddsaaz", "ds", "ddsaa",                                       "dds", "dds" };        substringSort(arr1, arr1.length, maxLen);         // Test 2        String[] arr2 = { "for", "rof" };        substringSort(arr2, arr2.length, maxLen);    }}

Python3

 # Alternative code to sort substringsdef substringSort(arr, n, maxLen):     count = [0]*(maxLen)    sortedArr = [""]*(maxLen)     # sort the input array    for i in range(n):         s = arr[i]        Len = len(s)         if (count[Len - 1] == 0) :            sortedArr[Len - 1] = s            count[Len - 1] = 1        elif (sortedArr[Len - 1] == s):            # repeated length should be the same string            count[Len - 1]+=1        else:            # two different strings with the same            # length input array cannot be sorted            print("Cannot be sorted")            return     # validate that each string is a substring    # of the following one    index = 0     # get first element    while (count[index] == 0):        index+=1     prev = index    prevString = sortedArr[prev]     index+=1         while index < maxLen:        if (count[index] != 0) :            current = sortedArr[index]            if (prevString in current):                prev = index                prevString = current            else:                print("Cannot be sorted")                return        index+=1     # The array is valid and sorted    # print the strings in order    for i in range(maxLen):        s = sortedArr[i]        for j in range(count[i]):            print(s) maxLen = 100   # Test 1arr1 = [ "d", "zddsaaz", "ds", "ddsaa", "dds", "dds" ]substringSort(arr1, len(arr1), maxLen) # Test 2arr2 = [ "for", "rof" ]substringSort(arr2, len(arr2), maxLen) # This code is contributed by mukesh07.

C#

 // C# Program to sort substringsusing System; class GFG{     public static void substringSort(String[] arr,                                int n, int maxLen)    {         int []count = new int[maxLen];        String[] sortedArr = new String[maxLen];        for(int i = 0; i < maxLen; i++)        {            count[i] = 0;            sortedArr[i] = "";         }         // sort the input array        for (int i = 0; i < n; i++)        {             String s = arr[i];            int len = s.Length;             if (count[len - 1] == 0)            {                sortedArr[len - 1] = s;                count[len - 1] = 1;            }            else if (ReferenceEquals(s,sortedArr[len - 1]))            {                 // repeated length should                // be the same string                count[len - 1]++;            }            else            {                 // two different strings with the same                // length input array cannot be sorted                Console.WriteLine("Cannot be sorted");                return;            }        }         // validate that each string is a         // substring of the following one        int index = 0;         // get first element        while (count[index] == 0)            index++;         int prev = index;        String prevString = sortedArr[prev];         index++;         for (; index < maxLen; index++)        {             if (count[index] != 0)            {                String current = sortedArr[index];                if (current.Contains(prevString))                {                    prev = index;                    prevString = current;                }                else                {                    Console.WriteLine("Cannot be sorted");                    return;                }            }        }         // The array is valid and sorted        // print the strings in order        for (int i = 0; i < maxLen; i++)        {            String s = sortedArr[i];            for (int j = 0; j < count[i]; j++)            {                Console.WriteLine(s);            }        }    }     public static void Main(String[] args)    {        int maxLen = 100;         // Test 1        String[] arr1 = { "d", "zddsaaz", "ds", "ddsaa",                                    "dds", "dds" };        substringSort(arr1, arr1.Length, maxLen);         // Test 2        String[] arr2 = { "for", "rof" };        substringSort(arr2, arr2.Length, maxLen);    }} // This code is contributed by PrinciRaj1992

Javascript


Output:
d
ds
dds
dds
ddsaa
zddsaaz
Cannot be sorted

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

My Personal Notes arrow_drop_up