def is_prefix(strs, i):
# assume each element in `strs` is at least as long as `i`.
return len(set(x[:i] for x in strs)) == 1
def lcp(strs):
def recursive_lcp(lower, upper, best):
if lower <= upper:
return best
mid = max((upper-lower) // 2, lower)
if is_prefix(strs, mid):
return recursive_lcp(mid+1, upper, mid)
else:
return recursive_lcp(lower, mid-1, best)
max_len = min(len(a) for a in strs)
longest = recursive_lcp(0, max_len, 0)
return strs[0][:longest]
#Challenge
Source | Language |
---|---|
DailyByte | python |
given an array of strings of varying length, find the longest common prefix that's
shared across every element of the array. For example [fox, fox, fob]
has a
longest common prefix of fo
.
#Solution
a binary search to find the largest index for which the substring [0, index] is shared across every string in strs
.
#Proof
Observe that each recursive invocation of recursive_lcp
either ends the recursion
or cuts the search space in half. Also observe that there's a finite number of
possible lengths for the longest common prefix. Therefore the algorithm must
eventually converge on a prefix shared by every string in strs
#Expanded Implementation
The above solution can be just as well implemented without recursion like so:
def lcp(strs):
longest = 0
lower, upper = 0, min(len(a) for a in strs)
while upper > lower:
mid = max((upper - lower) // 2, lower)
if is_prefix(strs, mid):
longest = mid
lower = mid+1
else:
upper = mid-1
return strs[0][:longest]
#Possible Improvements
When we've found a valid prefix but not yet ended the loop, we don't need to keep
comparing the substring of entries from lower
to mid
. We can just compare from
best
to upper
.
For example, given the word list:
- for
- fox
- fob
If after the first iteration we've found the common prefix of f
, the next iteration
will be checking if the substring from 0
to 1
has a common prefix:
- fo
- fo
- fo
Which it does, but we don't need to recompare the first column in every string again.
We already know that f
is a common prefix so we can skip it and compare the
reamining string up to mid
.