📜  查找给定列表中每个单词的最短唯一前缀|设置1(使用特里)

📅  最后修改于: 2021-04-17 11:16:56             🧑  作者: Mango

给定一个单词数组,找到所有最短的唯一前缀以表示给定数组中的每个单词。假设没有一个单词是另一个单词的前缀。

例子:

Input: arr[] = {"zebra", "dog", "duck", "dove"}
Output: dog, dov, du, z
Explanation: dog => dog
             dove = dov 
             duck = du
             z   => zebra 

Input: arr[] =  {"geeksgeeks", "geeksquiz", "geeksforgeeks"};
Output: geeksf, geeksg, geeksq}

一个简单的解决方案是考虑每个单词的每个前缀(从最短到最大),如果前缀不是任何其他字符串的前缀,则打印它。

一个有效的解决方案是使用Trie。这个想法是要在每个节点中保持一个计数。以下是步骤。

1)构造一个所有单词的特里。还要保持每个节点的频率(这里的频率是插入期间访问节点的次数)。此步骤的时间复杂度为O(N),其中N是所有单词中字符的总数。

2)现在,对于每个单词,我们找到最接近根的字符,其频率为1。单词的前缀是从根到该字符的路径。为此,我们可以从根开始遍历Trie。对于遍历的每个节点,我们都会检查其频率。如果频率为1,则将所有字符从根打印到该节点,并且不向下遍历此节点。

如果此步骤也是O(N),则时间复杂度,其中N是所有单词中字符的总数。

root
                / \
         (d, 3)/   \(z, 1)
              /     \
          Node1     Node2
           / \          \
     (o,2)/   \(u,1)     \(e,1)
         /     \          \
   Node1.1    Node1.2     Node2.1
      /  \         \            \
(g,1)/    \ (t,1)   \(c,1)       \(b,1)
    /      \         \            \ 
   Leaf   Leaf       Node1.2.1     Node2.1.1
   (dog)  (dot)        \               \
                         \(k, 1)          \(r, 1)
                          \                \   
                          Leaf           Node2.1.1.1
                          (duck)              \
                                                \(a,1)
                                                 \
                                                 Leaf
                                                 (zebra)

以下是上述想法的实现。

C++
// C++ program to print all prefixes that
// uniquely reprsent words.
#include
using namespace std;
  
#define MAX 256
  
// Maximum length of an input word
#define MAX_WORD_LEN 500
  
// Trie Node.
struct trieNode
{
    struct trieNode *child[MAX];
    int freq;  // To store frequency
};
  
// Function to create a new trie node.
struct trieNode *newTrieNode(void)
{
    struct trieNode *newNode = new trieNode;
    newNode->freq   = 1;
    for (int i = 0; ichild[i] = NULL;
    return newNode;
}
  
// Method to insert a new string into Trie
void insert(struct trieNode *root, string str)
{
    // Length of the URL
    int len = str.length();
    struct trieNode *pCrawl = root;
  
    // Traversing over the length of given str.
    for (int level = 0; levelchild[index])
            pCrawl->child[index] = newTrieNode();
        else
           (pCrawl->child[index]->freq)++;
  
        // Move to the child
        pCrawl = pCrawl->child[index];
    }
}
  
// This function prints unique prefix for every word stored
// in Trie. Prefixes one by one are stored in prefix[].
// 'ind' is current index of prefix[]
void findPrefixesUtil(struct trieNode *root, char prefix[],
                      int ind)
{
    // Corner case
    if (root == NULL)
       return;
  
    // Base case
    if (root->freq == 1)
    {
       prefix[ind] = '\0';
       cout << prefix << " ";
       return;
    }
  
    for (int i=0; ichild[i] != NULL)
       {
           prefix[ind] = i;
           findPrefixesUtil(root->child[i], prefix, ind+1);
       }
    }
}
  
// Function to print all prefixes that uniquely
// represent all words in arr[0..n-1]
void findPrefixes(string arr[], int n)
{
    // Construct a Trie of all words
    struct trieNode *root = newTrieNode();
    root->freq = 0;
    for (int i = 0; i


Java
// Java program to print all prefixes that
// uniquely represent words.
public class Unique_Prefix_Trie {
       
    static final int MAX  = 256;
       
    // Maximum length of an input word
    static final int MAX_WORD_LEN = 500;
       
    // Trie Node.
    static class TrieNode
    {
        TrieNode[] child = new TrieNode[MAX];
        int freq;  // To store frequency
        TrieNode() {
            freq =1;
            for (int i = 0; i < MAX; i++)
                child[i] = null;
        }
    }
    static TrieNode root;
      
    // Method to insert a new string into Trie
    static void insert(String str)
    {
        // Length of the URL
        int len = str.length();
        TrieNode pCrawl = root;
       
        // Traversing over the length of given str.
        for (int level = 0; level


C#
// C# program to print all prefixes that 
// uniquely represent words. 
using System;
  
public class Unique_Prefix_Trie 
{ 
      
    static readonly int MAX = 256; 
      
    // Maximum length of an input word 
    static readonly int MAX_WORD_LEN = 500; 
      
    // Trie Node. 
    public class TrieNode 
    { 
        public TrieNode[] child = new TrieNode[MAX]; 
        public int freq; // To store frequency 
        public TrieNode() 
        { 
            freq = 1; 
            for (int i = 0; i < MAX; i++) 
                child[i] = null; 
        } 
    } 
    static TrieNode root; 
      
    // Method to insert a new string into Trie 
    static void insert(String str) 
    { 
        // Length of the URL 
        int len = str.Length; 
        TrieNode pCrawl = root; 
      
        // Traversing over the length of given str. 
        for (int level = 0; level


输出:

dog dov du z

感谢Gaurav Ahirwar提出上述解决方案。