Find shortest unique prefix for every word in a given list (Using Trie)

Last Updated : 22 Jun, 2026

Given an array of strings arr[ ], find the shortest prefix of each string that uniquely identifies it among all strings in the array. A prefix is unique if it is not a prefix of any other string in the array. 

Note: No string in the array is a prefix of another string

.Examples: 

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

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

Try It Yourself
redirect icon

[Naive Approach] Prefix Check with Nested Loops - O(n² × L) Time and O(n × L) Space

For each word, try all prefix lengths from 1 to full word. For each prefix, check if it is unique among all other words. Return first unique prefix found.

Do the following for each word in array

  • For len from 1 to word length, extract prefix of length len and check if prefix is unique by comparing with all other words
  • If unique, add to answer and break
  • If no unique prefix found, add full word
C++
#include <bits/stdc++.h>
using namespace std;

vector<string> findPrefixes(vector<string>& arr) {
    vector<string> ans;

    // Find answer for each word
    for (int i = 0; i < arr.size(); i++) {
        string word = arr[i];
        bool found = false;

        // Try all possible prefix lengths
        for (int len = 1; len <= word.size(); len++) {
            string prefix = word.substr(0, len);

            bool unique = true;

            // Compare with every other word
            for (int j = 0; j < arr.size(); j++) {
                if (i == j)
                    continue;

                if (arr[j].size() >= len &&
                    arr[j].substr(0, len) == prefix) {
                    unique = false;
                    break;
                }
            }

            if (unique) {
                ans.push_back(prefix);
                found = true;
                break;
            }
        }

        // In case no unique prefix exists
        if (!found)
            ans.push_back(word);
    }

    return ans;
}

int main() {
    vector<string> arr = {"zebra", "dog", "duck", "dove"};

    vector<string> ans = findPrefixes(arr);

    for (string &s : ans)
        cout << s << " ";

    return 0;
}
Java
import java.util.*;

class GfG {

    static ArrayList<String> findPrefixes(ArrayList<String> arr) {
        ArrayList<String> ans = new ArrayList<>();

        // Find answer for each word
        for (int i = 0; i < arr.size(); i++) {
            String word = arr.get(i);
            boolean found = false;

            // Try all possible prefix lengths
            for (int len = 1; len <= word.length(); len++) {
                String prefix = word.substring(0, len);
                boolean unique = true;

                // Compare with every other word
                for (int j = 0; j < arr.size(); j++) {
                    if (i == j)
                        continue;

                    String other = arr.get(j);

                    if (other.length() >= len &&
                        other.substring(0, len).equals(prefix)) {
                        unique = false;
                        break;
                    }
                }

                // First unique prefix found
                if (unique) {
                    ans.add(prefix);
                    found = true;
                    break;
                }
            }

            // If no unique prefix exists
            if (!found)
                ans.add(word);
        }

        return ans;
    }

    public static void main(String[] args) {
        ArrayList<String> arr = new ArrayList<>(
            Arrays.asList("zebra", "dog", "duck", "dove")
        );

        ArrayList<String> ans = findPrefixes(arr);

        System.out.println("Shortest Unique Prefixes:");
        for (String s : ans) {
            System.out.print(s + " ");
        }
    }
}
Python
# Python program to find shortest unique prefix using brute force

def findPrefixes(arr):
    ans = []
    
    # Find answer for each word
    for i in range(len(arr)):
        word = arr[i]
        found = False
        
        # Try all possible prefix lengths
        for length in range(1, len(word) + 1):
            prefix = word[:length]
            unique = True
            
            # Compare with every other word
            for j in range(len(arr)):
                if i == j:
                    continue
                
                if len(arr[j]) >= length and arr[j][:length] == prefix:
                    unique = False
                    break
            
            if unique:
                ans.append(prefix)
                found = True
                break
        
        # In case no unique prefix exists
        if not found:
            ans.append(word)
    
    return ans

# Driver code
if __name__ == "__main__":
    arr = ["zebra", "dog", "duck", "dove"]
    
    ans = findPrefixes(arr)
    
    print(' '.join(ans))
C#
using System;
using System.Collections.Generic;

class GfG
{
    static List<string> findPrefixes(List<string> arr)
    {
        List<string> ans = new List<string>();

        // Find answer for each word
        for (int i = 0; i < arr.Count; i++)
        {
            string word = arr[i];
            bool found = false;

            // Try all possible prefix lengths
            for (int len = 1; len <= word.Length; len++)
            {
                string prefix = word.Substring(0, len);
                bool unique = true;

                // Compare with every other word
                for (int j = 0; j < arr.Count; j++)
                {
                    if (i == j)
                        continue;

                    string other = arr[j];

                    if (other.Length >= len &&
                        other.Substring(0, len) == prefix)
                    {
                        unique = false;
                        break;
                    }
                }

                if (unique)
                {
                    ans.Add(prefix);
                    found = true;
                    break;
                }
            }

            if (!found)
                ans.Add(word);
        }

        return ans;
    }

    static void Main()
    {
        List<string> arr = new List<string>
        {
            "zebra", "dog", "duck", "dove"
        };

        List<string> ans = findPrefixes(arr);

        Console.WriteLine("Shortest Unique Prefixes:");
        foreach (string s in ans)
            Console.Write(s + " ");
    }
}
JavaScript
// JavaScript program to find shortest unique prefix using brute force

function findPrefixes(arr) {
    let ans = [];
    
    // Find answer for each word
    for (let i = 0; i < arr.length; i++) {
        let word = arr[i];
        let found = false;
        
        // Try all possible prefix lengths
        for (let len = 1; len <= word.length; len++) {
            let prefix = word.substring(0, len);
            let unique = true;
            
            // Compare with every other word
            for (let j = 0; j < arr.length; j++) {
                if (i === j)
                    continue;
                
                if (arr[j].length >= len &&
                    arr[j].substring(0, len) === prefix) {
                    unique = false;
                    break;
                }
            }
            
            if (unique) {
                ans.push(prefix);
                found = true;
                break;
            }
        }
        
        // In case no unique prefix exists
        if (!found)
            ans.push(word);
    }
    
    return ans;
}

// Driver code
const arr = ["zebra", "dog", "duck", "dove"];

const ans = findPrefixes(arr);

console.log(ans.join(' '));

Output
z dog du dov 

[Expected Approach] Trie with Frequency Tracking - O(n × L) Time and O(n × L) Space

Insert all words into a Trie where each node stores frequency count of how many words pass through it. For each word, traverse from root until a node with frequency 1 is found, which gives the shortest unique prefix.

  • Insert all words into Trie, incrementing frequency at each node
  • For each word, traverse from root
  • At each node, check if frequency is 1
  • Stop at first node with frequency 1, that prefix is unique
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<string> findPrefixes(vector<string>& 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<string> arr = {"zebra", "dog", "duck", "dove"};
    vector<string> ans = findPrefixes(arr);
    for (string val: ans) {
        cout << val << " ";
    }
    cout << endl;
}
Java
import java.util.*;

class TrieNode {
    TrieNode[] child;
    int freq;

    TrieNode() {
        child = new TrieNode[26];
        freq = 0;
    }
}

class Solution {

    static void insert(TrieNode root, String word) {
        TrieNode curr = root;

        for (char ch : word.toCharArray()) {
            int idx = ch - 'a';

            if (curr.child[idx] == null) {
                curr.child[idx] = new TrieNode();
            }

            curr = curr.child[idx];
            curr.freq++;
        }
    }

    static String getPrefix(TrieNode root, String word) {
        TrieNode curr = root;
        StringBuilder sb = new StringBuilder();

        for (char ch : word.toCharArray()) {
            curr = curr.child[ch - 'a'];
            sb.append(ch);

            if (curr.freq == 1) {
                break;
            }
        }

        return sb.toString();
    }

    public ArrayList<String> findPrefixes(ArrayList<String> arr) {
        TrieNode root = new TrieNode();

        for (String word : arr) {
            insert(root, word);
        }

        ArrayList<String> ans = new ArrayList<>();

        for (String word : arr) {
            ans.add(getPrefix(root, word));
        }

        return ans;
    }
}

public class Main {
    public static void main(String[] args) {
        ArrayList<String> arr = new ArrayList<>(
                Arrays.asList("zebra", "dog", "duck", "dove"));

        Solution ob = new Solution();
        ArrayList<String> ans = ob.findPrefixes(arr);

        for (String s : ans) {
            System.out.print(s + " ");
        }
    }
}
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#
using System;
using System.Collections.Generic;

class Node {
    public Node[] children;
    public int freq;

    public Node()
    {
        children = new Node[26];
        freq = 0;
    }
}

class Solution {

    static void Insert(Node root, string word)
    {
        Node curr = root;

        foreach(char ch in word)
        {
            int idx = ch - 'a';

            if (curr.children[idx] == null)
                curr.children[idx] = new Node();

            curr = curr.children[idx];
            curr.freq++;
        }
    }

    static string GetPrefix(Node root, string word)
    {
        Node curr = root;
        string prefix = "";

        foreach(char ch in word)
        {
            curr = curr.children[ch - 'a'];
            prefix += ch;

            if (curr.freq == 1)
                break;
        }

        return prefix;
    }

    public List<string> findPrefixes(List<string> arr)
    {
        Node root = new Node();

        foreach(string word in arr) Insert(root, word);

        List<string> ans = new List<string>();

        foreach(string word in arr)
            ans.Add(GetPrefix(root, word));

        return ans;
    }
    static void Main()
    {
        List<string> arr
            = new List<string>{ "zebra", "dog", "duck",
                                "dove" };

        Solution ob = new Solution();
        List<string> ans = ob.findPrefixes(arr);

        foreach(string s in ans) Console.Write(s + " ");
    }
}
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(" "));

Output
z dog du dov 
Comment