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 => dov

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

Try It Yourselfredirect icon

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:

**Trie Illustration:

trie

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) - 1

def 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 result

if 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)