📌  相关文章
📜  使用Trie排序字符串(或单词)的数组设置2(处理重复项)

📅  最后修改于: 2021-05-06 21:54:34             🧑  作者: Mango

给定一个字符串数组,请按字母(字典)顺序打印它们。如果输入数组中有重复项,我们需要打印所有出现的情况。
例子:

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

先决条件: Trie | (插入和搜索)。
方法:在对上一个字符串数组进行排序时,仅打印一次出现的重复字符串。在这篇文章中,所有重复的字符串都按字典顺序打印。要按字母顺序打印字符串,我们必须先将它们插入到trie中,然后执行预遍历以按字母顺序打印。特里的节点包含一个index []数组,该数组存储以该节点结尾的所有arr []字符串的索引位置。除trie的叶节点外,其他所有节点的index []数组大小均为0。
下面是上述方法的实现。

C++
// C++ implementation to sort an array
// of strings using Trie
#include 
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 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
// Java implementation
// to sort an array of
// strings using Trie
import java.util.*;
 
class Trie {
 
    private Node rootNode;
 
    /*to make new trie*/
    Trie()
    {
        rootNode = null;
    }
 
    // function to insert
    // a string in trie
    void insert(String key, int index)
    {
        // making a new path
        // if not already
        if (rootNode == null)
        {
            rootNode = new Node();
        }
 
        Node currentNode = rootNode;
 
        for (int i = 0;i < key.length();i++)
        {
            char keyChar = key.charAt(i);
     
            if (currentNode.getChild(keyChar) == null)
            {
                currentNode.addChild(keyChar);
            }
             
            // go to next node
            currentNode = currentNode.getChild(keyChar);
        }
 
        // Mark leaf (end of string)
        // and store index of 'str'
        // in index[]
        currentNode.addIndex(index);
    }
 
    void traversePreorder(String[] array)
    {
        traversePreorder(rootNode, array);
    }
 
    // function for preorder
    // traversal of trie
    private void traversePreorder(Node node,
                             String[] array)
    {
        if (node == null)
        {
            return;
        }
 
        if (node.getIndices().size() > 0)
        {
            for (int index : node.getIndices())
            {
                System.out.print(array[index] + " ");
            }
        }
 
        for (char index = 'a';index <= 'z';index++)
        {
            traversePreorder(node.getChild(index), array);
        }
    }
 
    private static class Node {
 
        private Node[] children;
        private List indices;
 
        Node()
        {
            children = new Node[26];
            indices = new ArrayList<>(0);
        }
 
        Node getChild(char index)
        {
            if (index < 'a' || index > 'z')
            {
                return null;
            }
             
            return children[index - 'a'];
        }
 
        void addChild(char index)
        {
            if (index < 'a' || index > 'z')
            {
                return;
            }
             
            Node node = new Node();
            children[index - 'a'] = node;
        }
 
        List getIndices()
        {
            return indices;
        }
 
        void addIndex(int index)
        {
            indices.add(index);
        }
    }
}
 
class SortStrings {
 
    // Driver program
    public static void main(String[] args)
    {
        String[] array = { "abc", "xyz",
                    "abcd", "bcd", "abc" };
        printInSortedOrder(array);
    }
 
    // function to sort an array
    // of strings using Trie
    private static void printInSortedOrder(String[] array)
    {
        Trie trie = new Trie();
         
        for (int i = 0;i < array.length;i++)
        {
            trie.insert(array[i], i);
        }
         
        trie.traversePreorder(array);
    }
}
 
// Contributed by Harikrishnan Rajan


C#
// C# implementation
// to sort an array of
// strings using Trie
using System;
using System.Collections.Generic;
 
public class Trie
{
 
    public Node rootNode;
 
    /* to make new trie*/
    public Trie()
    {
        rootNode = null;
    }
 
    // function to insert
    // a string in trie
    public void insert(String key, int index)
    {
        // making a new path
        // if not already
        if (rootNode == null)
        {
            rootNode = new Node();
        }
 
        Node currentNode = rootNode;
 
        for (int i = 0;i < key.Length;i++)
        {
            char keyChar = key[i];
     
            if (currentNode.getChild(keyChar) == null)
            {
                currentNode.addChild(keyChar);
            }
             
            // go to next node
            currentNode = currentNode.getChild(keyChar);
        }
 
        // Mark leaf (end of string)
        // and store index of 'str'
        // in index[]
        currentNode.addIndex(index);
    }
 
    public void traversePreorder(String[] array)
    {
        traversePreorder(rootNode, array);
    }
 
    // function for preorder
    // traversal of trie
    public void traversePreorder(Node node,
                            String[] array)
    {
        if (node == null)
        {
            return;
        }
 
        if (node.getIndices().Count > 0)
        {
            foreach (int index in node.getIndices())
            {
                Console.Write(array[index] + " ");
            }
        }
 
        for (char index = 'a';index <= 'z';index++)
        {
            traversePreorder(node.getChild(index), array);
        }
    }
 
    public class Node
    {
 
        public Node[] children;
        public List indices;
 
        public Node()
        {
            children = new Node[26];
            indices = new List(0);
        }
 
        public Node getChild(char index)
        {
            if (index < 'a' || index > 'z')
            {
                return null;
            }
             
            return children[index - 'a'];
        }
 
        public void addChild(char index)
        {
            if (index < 'a' || index > 'z')
            {
                return;
            }
             
            Node node = new Node();
            children[index - 'a'] = node;
        }
 
        public List getIndices()
        {
            return indices;
        }
 
        public void addIndex(int index)
        {
            indices.Add(index);
        }
    }
}
 
public class SortStrings
{
 
    // Driver code
    public static void Main(String[] args)
    {
        String[] array = { "abc", "xyz",
                    "abcd", "bcd", "abc" };
        printInSortedOrder(array);
    }
 
    // function to sort an array
    // of strings using Trie
    static void printInSortedOrder(String[] array)
    {
        Trie trie = new Trie();
         
        for (int i = 0;i < array.Length;i++)
        {
            trie.insert(array[i], i);
        }
         
        trie.traversePreorder(array);
    }
}
 
// This code has been contributed by 29AjayKumar


Python3
# Python implementation to sort an array
# of strings using Trie
from typing import List
MAX_CHAR = 26
class Trie:
    def __init__(self) -> None:
 
        # 'index' vectors size is greater than
        # 0 when node/ is a leaf node, otherwise
        # size is 0;
        self.index = []
        self.child = [None for _ in range(MAX_CHAR)]
 
# function to insert a string in trie
def insert(root: Trie, string: str, index: int) -> None:
    node = root
    for i in range(len(string)):
 
        # taking ascii value to find index of
        # child node
        ind = ord(string[i]) - ord('a')
 
        # making a new path if not already
        if (node.child[ind] == None):
            node.child[ind] = Trie()
 
        # go to next node
        node = node.child[ind]
 
    # Mark leaf (end of string) and store
    # index of 'str' in index[]
    (node.index).append(index)
 
# function for preorder traversal of trie
def preorder(node: Trie, arr: List[str]) -> None:
 
    # if node is empty
    if (node == None):
        return
    for i in range(MAX_CHAR):
        if (node.child[i] != None):
 
            # if leaf node then print all the strings
            # for (node.child[i].index).size() > 0)
            for j in range(len(node.child[i].index)):
                print(arr[node.child[i].index[j]], end = " ")
            preorder(node.child[i], arr)
 
# function to sort an array
# of strings using Trie
def printSorted(arr: List[str], n: int) -> None:
    root = Trie()
 
    # insert all strings of dictionary into trie
    for i in range(n):
        insert(root, arr[i], i)
 
    # print strings in lexicographic order
    preorder(root, arr)
 
# Driver program to test above
if __name__ == "__main__":
 
    arr = ["abc", "xyz", "abcd", "bcd", "abc"]
    n = len(arr)
    printSorted(arr, n)
 
# This code is contributed by sanjeev2552


输出:

abc abc abcd bcd xyz

时间复杂度:最坏的情况是每个字符串都以不同的字符开头时。在这种情况下,它将访问每个字符串的每个字符的所有节点。因此,最坏情况下的时间复杂度将是每个字符串长度的总和,即O(| S1 | + | S2 | + | S3 | +…+ | Sn |)其中| S |是字符串的长度。