Substring Sort

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.

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java code to sort substrings
import 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<String>() {
            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 cann'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);
    }
}

chevron_right


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

Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Alternative code to sort substrings
import 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);
    }
}

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# Program to sort substrings
using 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

chevron_right


Output:

d
ds
dds
dds
ddsaa
zddsaaz
Cannot be sorted


My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Improved By : princiraj1992