Problem Statement
Given an array of strings, find the shortest prefix of every word such that the prefix uniquely identifies that word among all other words.
Note: No word is a prefix of another word.
Example 1
Input
arr = {"zebra", "dog", "duck", "dove"}
Output
z dog du dov
Explanation
zuniquely identifieszebra.dogis needed becausedois shared withdove.duuniquely identifiesduck.dovuniquely identifiesdove.
Example 2
Input
arr = {"geeksgeeks", "geeksquiz", "geeksforgeeks"}
Output
geeksg geeksq geeksf
Intuition
A brute-force solution would compare every word with every other word.
For each word:
Check the prefix of length
1.If it is not unique, check the prefix of length
2.Continue until a unique prefix is found.
This requires comparing each word with every other word.
Time Complexity
O(N² × L)
Where:
N= Number of wordsL= Length of each word
This approach becomes inefficient for large inputs.
Efficient Approach: Trie
A Trie (Prefix Tree) is specially designed to store strings based on their prefixes.
Instead of repeatedly comparing strings, we store all words in a Trie and count how many words pass through each node.
Key Observation
Suppose we insert:
dog
duck
dove
The Trie looks like:
(root)
|
d (3)
|
o (3)
/ \
g v
(1) (1)
|
u
(1)
The numbers represent how many words pass through each node.
For dog:
d -> count = 3
o -> count = 3
g -> count = 1
The first node having count = 1 is g.
Therefore:
dog
is the shortest unique prefix.
Algorithm
Step 1
Create a Trie.
Each node stores:
childrencount
static class TrieNode{
TrieNode[] child = new TrieNode[26];
int count;
}
Step 2
Insert every word.
While inserting:
Increase the count of every node visited.
Example:
Insert:
duck
root
|
d(count=1)
|
u(count=1)
|
c(count=1)
|
k(count=1)
Now insert:
dove
root
|
d(count=2)
|
o(count=1)
Notice:
d.count = 2
because two words start with d.
Step 3
Traverse every word again.
Stop when:
count == 1
because no other word passes through that node.
That prefix is unique.
Dry Run
Input
["zebra","dog","duck","dove"]
After inserting "zebra"
root
|
z(1)
|
e(1)
|
b(1)
|
r(1)
|
a(1)
Insert "dog"
root
├── z(1)
└── d(1)
|
o(1)
|
g(1)
Insert "duck"
root
└── d(2)
|
o(1)
u(1)
Now:
d.count = 2
Insert "dove"
root
└── d(3)
|
o(2)
/ \
g v
Final counts:
d = 3
o = 2
g = 1
u = 1
v = 1
Finding Prefixes
Word = zebra
z
count = 1
Stop.
Answer:
z
Word = dog
d
count = 3
Continue
o
count = 2
Continue
g
count = 1
Stop
Answer:
dog
Word = duck
d
count = 3
Continue
u
count = 1
Stop
Answer:
du
Word = dove
d
count = 3
Continue
o
count = 2
Continue
v
count = 1
Stop
Answer:
dov
Final Output
z
dog
du
dov
Understanding the Code
Trie Node
static class TrieNode {
TrieNode[] child = new TrieNode[26];
int count = 0;
}
Explanation
Each Trie node contains:
TrieNode[] child = new TrieNode[26];
This stores pointers for:
a
b
c
...
z
For example:
child[0] -> a
child[1] -> b
child[25] -> z
The variable:
int count;
stores:
How many words pass through this node.

Join the conversation! Your thoughts help the community grow.