Find shortest unique prefix for every word in a given list (Using Trie) (original) (raw)
Last Updated : 23 Jul, 2025
Given an array of words, the task is to find the **shortest unique prefixes to represent each word in the given array. Assume that no word is prefix of another.
**Examples:
arr[] = {"zebra", "dog", "duck", "dove"}
**Output: z dog du dov
**Explanation:
z => zebra
dog => dog
duck => du
dove => dovarr[] = {"geeksgeeks", "geeksquiz", "geeksforgeeks"};
**Output: geeksg geeksq geeksf
A **Simple Solution is to consider every prefix of every word (starting from the shortest to largest), and if that is not a prefix of any other string, then print it.
**Approach:
The idea is to use trie and maintain a frequency count at each node representing how many words pass through that node. For each word, we traverse the trie along its path until we find a node with frequency 1, indicating no other word shares this prefix - the index at this point gives us the ending index of our minimum unique prefix.
**Step-by-step approach:
- Build a trie with all words and maintain frequency count at each node
- For each word, traverse the trie until finding a node with frequency 1 to get its unique prefix
- Create substring from start to end index of found prefix and add to result
**Trie Illustration:

trie
C++ `
// C++ program to find shortest unique // prefix for every word in a given list #include <bits/stdc++.h> using namespace std;
class Node { private: vector<Node*> children; int freq; char ch;
public: Node(char x) { freq = 0; ch = x; children = vector<Node*>(26, nullptr); }
// Insert a word into the Trie
void insert(string& word) {
Node* curr = this;
for(char c : word) {
if(curr->children[c-'a'] == nullptr) {
curr->children[c-'a'] = new Node(c);
}
curr = curr->children[c-'a'];
curr->freq++;
}
}
// Find the ending index of minimum
// unique prefix for given word
int findPrefix(string& word) {
Node* curr = this;
for(int i = 0; i < word.length(); i++) {
curr = curr->children[word[i]-'a'];
// If frequency is 1, we found the unique prefix
if(curr->freq == 1) {
return i;
}
}
return word.length() - 1;
}
void deleteTrie(Node* root) {
if (root==nullptr) return;
for (int i=0; i<26; i++) {
deleteTrie(root->children[i]);
delete root->children[i];
}
}};
vector findPrefixes(vector& arr) { int n = arr.size();
// Create root node of Trie
Node* root = new Node('*');
// Insert all words into the Trie
for(int i=0; i<n; i++) {
root->insert(arr[i]);
}
// Vector to store result prefixes
vector<string> result;
// Find minimum unique prefix for each word
for(int i=0; i<n; i++) {
string word = arr[i];
// Get ending index of minimum prefix
int endIndex = root->findPrefix(word);
// Add substring from start to endIndex to result
result.push_back(word.substr(0, endIndex + 1));
}
// Free up the trie space.
root->deleteTrie(root);
return result;}
int main() { vector arr = {"zebra", "dog", "duck", "dove"}; vector ans = findPrefixes(arr); for (string val: ans) { cout << val << " "; } cout << endl; }
Java
// Java program to find shortest unique // prefix for every word in a given list
import java.util.*;
class GfG {
static String[] findPrefixes(String[] arr) {
int n = arr.length;
// Create root node of Trie
Node root = new Node('*');
// Insert all words into the Trie
for(int i = 0; i < n; i++) {
root.insert(arr[i]);
}
// Array to store result prefixes
String[] result = new String[n];
// Find minimum unique prefix for each word
for(int i = 0; i < n; i++) {
String word = arr[i];
// Get ending index of minimum prefix
int endIndex = root.findPrefix(word);
// Add substring from start to endIndex to result
result[i] = word.substring(0, endIndex + 1);
}
// Free up the trie space.
root.deleteTrie(root);
return result;
}
public static void main(String[] args) {
String[] arr = {"zebra", "dog", "duck", "dove"};
String[] ans = findPrefixes(arr);
for (String val : ans) {
System.out.print(val + " ");
}
System.out.println();
}}
class Node { private Node[] children; private int freq; private char ch;
Node(char x) {
freq = 0;
ch = x;
children = new Node[26];
}
// Insert a word into the Trie
void insert(String word) {
Node curr = this;
for(char c : word.toCharArray()) {
if(curr.children[c - 'a'] == null) {
curr.children[c - 'a'] = new Node(c);
}
curr = curr.children[c - 'a'];
curr.freq++;
}
}
// Find the ending index of minimum
// unique prefix for given word
int findPrefix(String word) {
Node curr = this;
for(int i = 0; i < word.length(); i++) {
curr = curr.children[word.charAt(i) - 'a'];
// If frequency is 1, we found the unique prefix
if(curr.freq == 1) {
return i;
}
}
return word.length() - 1;
}
void deleteTrie(Node root) {
if (root == null) return;
for (int i = 0; i < 26; i++) {
deleteTrie(root.children[i]);
root.children[i] = null;
}
}}
Python
Python program to find shortest unique
prefix for every word in a given list
class Node: def init(self): self.freq = 0 self.children = [None] * 26
# Insert a word into the Trie
def insert(self, word):
curr = self
for c in word:
if curr.children[ord(c) - ord('a')] is None:
curr.children[ord(c) - ord('a')] = Node()
curr = curr.children[ord(c) - ord('a')]
curr.freq += 1
# Find the ending index of minimum
# unique prefix for given word
def findPrefix(self, word):
curr = self
for i in range(len(word)):
curr = curr.children[ord(word[i]) - ord('a')]
# If frequency is 1, we found the unique prefix
if curr.freq == 1:
return i
return len(word) - 1def findPrefixes(arr): n = len(arr)
# Create root node of Trie
root = Node()
# Insert all words into the Trie
for i in range(n):
root.insert(arr[i])
# List to store result prefixes
result = []
# Find minimum unique prefix for each word
for i in range(n):
word = arr[i]
# Get ending index of minimum prefix
endIndex = root.findPrefix(word)
# Add substring from start to endIndex to result
result.append(word[:endIndex + 1])
return resultif name == "main": arr = ["zebra", "dog", "duck", "dove"] ans = findPrefixes(arr) print(" ".join(ans))
C#
// C# program to find shortest unique // prefix for every word in a given list
using System; using System.Collections.Generic;
class GfG { static List findPrefixes(string[] arr) { int n = arr.Length;
// Create root node of Trie
Node root = new Node();
// Insert all words into the Trie
for (int i = 0; i < n; i++) {
root.insert(arr[i]);
}
// List to store result prefixes
List<string> result = new List<string>();
// Find minimum unique prefix for each word
for (int i = 0; i < n; i++) {
string word = arr[i];
// Get ending index of minimum prefix
int endIndex = root.findPrefix(word);
// Add substring from start to endIndex to result
result.Add(word.Substring(0, endIndex + 1));
}
// Free up the trie space.
root.deleteTrie(root);
return result;
}
static void Main() {
string[] arr = { "zebra", "dog", "duck", "dove" };
List<string> ans = findPrefixes(arr);
Console.WriteLine(string.Join(" ", ans));
}}
class Node { private Node[] children; private int freq;
public Node() {
freq = 0;
children = new Node[26];
}
// Insert a word into the Trie
public void insert(string word) {
Node curr = this;
foreach (char c in word) {
if (curr.children[c - 'a'] == null) {
curr.children[c - 'a'] = new Node();
}
curr = curr.children[c - 'a'];
curr.freq++;
}
}
// Find the ending index of minimum
// unique prefix for given word
public int findPrefix(string word) {
Node curr = this;
for (int i = 0; i < word.Length; i++) {
curr = curr.children[word[i] - 'a'];
// If frequency is 1, we found the unique prefix
if (curr.freq == 1) {
return i;
}
}
return word.Length - 1;
}
public void deleteTrie(Node root) {
if (root == null) return;
for (int i = 0; i < 26; i++) {
deleteTrie(root.children[i]);
root.children[i] = null;
}
}}
JavaScript
// JavaScript program to find shortest unique // prefix for every word in a given list
class Node { constructor() { this.freq = 0; this.children = Array(26).fill(null); }
// Insert a word into the Trie
insert(word) {
let curr = this;
for (let c of word) {
let index = c.charCodeAt(0) - 'a'.charCodeAt(0);
if (!curr.children[index]) {
curr.children[index] = new Node();
}
curr = curr.children[index];
curr.freq++;
}
}
// Find the ending index of minimum
// unique prefix for given word
findPrefix(word) {
let curr = this;
for (let i = 0; i < word.length; i++) {
curr = curr.children[word[i].charCodeAt(0) - 'a'.charCodeAt(0)];
if (curr.freq === 1) {
return i;
}
}
return word.length - 1;
}}
function findPrefixes(arr) { let root = new Node();
arr.forEach(word => root.insert(word));
return arr.map(word => word.substring(0, root.findPrefix(word) + 1));}
let arr = ["zebra", "dog", "duck", "dove"]; console.log(findPrefixes(arr).join(" "));
`
**Time Complexity: O(n*m) where n is the length of the array and m is the length of the longest word.
**Auxiliary Space: O(n*m)