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 => dovInput: arr[] = {"geeksgeeks", "geeksquiz", "geeksforgeeks"}
Output: geeksg geeksq geeksf
Explanation: geeksgeeks => geeksg, geeksquiz => geeksq, geeksforgeeks => geeksf
Table of Content
[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
#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;
}
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 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))
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 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

// 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;
}
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 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))
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 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