给定一个单词数组,找到所有最短的唯一前缀以表示给定数组中的每个单词。假设没有一个单词是另一个单词的前缀。
例子:
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提出上述解决方案。