📜  子串排序

📅  最后修改于: 2021-04-30 03:09:12             🧑  作者: Mango

给定n个字符串,我们需要对这些字符串进行排序,以使每个字符串都是其后所有字符串的子字符串。如果无法排序,请打印相同的内容。

例子:

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

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

观察1
如果A的B子串
那么A的长度<= B的长度

观察2
如果(B的A子串)和(C的B子串)
然后是C的子字符串

解决方案
根据以上两个观察结果,解决方案如下

  1. 将所有字符串从短到长排序
  2. 验证每个字符串是以下字符串的子字符串

如果我们验证每个字符串是后续字符串的子字符串,则根据观察2,每个字符串都是其后所有字符串的子字符串。

// 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() {
            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);
    }
}
输出:
d
ds
dds
ddsaa
Cannot be sorted

复杂
时间复杂度:O(n log n),其中n是字符串。

替代方法
为了提高时间复杂度,仅在指定字符串的最大长度时,才可以使用计数排序。
假设“ maxLen”是输入字符串的最大长度。在这种情况下,解决方案如下:

  1. 创建长度为maxLen的数组
  2. 对输入字符串排序,以使长度为1的字符串位于数组的第一位
  3. 如果有两个或两个以上的字符串具有相同的长度,则它们必须相等,否则无法对字符串进行排序
  4. 验证每个字符串是否是下一个较长字符串的子字符串
Java
// 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);
    }
}


C#
// 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


输出:
d
ds
dds
dds
ddsaa
zddsaaz
Cannot be sorted