Given an array of strings words
, return the smallest string that contains each string in words
as a substring. If there are multiple valid strings of the smallest length, return any of them.
You may assume that no string in words
is a substring of another string in words
.
Example 1:
Input: words = ["alex","loves","leetcode"]
Output: "alexlovesleetcode"
Explanation: All permutations of "alex","loves","leetcode" would also be accepted.
Example 2:
Input: words = ["catg","ctaagt","gcta","ttca","atgcatc"]
Output: "gctaagttcatgcatc"
Clarifications:
words
is empty?Let's explore approaches to solve the problem of finding the shortest superstring containing all strings in a given array.
The most straightforward approach is to generate all possible permutations of the input strings and check for each permutation, how the strings can be merged to form a superstring. The shortest of all such superstrings will be our result.
words
array.from itertools import permutations
def overlap(s1, s2):
n1, n2 = len(s1), len(s2)
for i in range(min(n1, n2), 0, -1):
if s1[n1-i:] == s2[:i]:
return i
return 0
def solve_brute_force(words):
shortest = None
for p in permutations(words):
current = list(p)
merged = current[0]
for i in range(1, len(current)):
o = overlap(merged, current[i])
merged += current[i][o:]
if shortest is None or len(merged) < len(shortest):
shortest = merged
return shortest
A more efficient approach utilizes a greedy strategy combined with dynamic programming principles to compute overlaps.
Algorithm:
Code (Python):
def solve_optimal(words):
n = len(words)
overlaps = [[0] * n for _ in range(n)]
for i in range(n):
for j in range(n):
if i != j:
overlaps[i][j] = overlap(words[i], words[j])
dp = [[('') for _ in range(n)] for _ in range(1 << n)]
for mask in range(1, 1 << n):
for i in range(n):
if (mask >> i) & 1:
if mask == (1 << i):
dp[mask][i] = words[i]
else:
for j in range(n):
if i != j and ((mask >> j) & 1):
prev_mask = mask ^ (1 << i)
candidate = dp[prev_mask][j] + words[i][overlaps[j][i]:]
if dp[mask][i] == '' or len(candidate) < len(dp[mask][i]):
dp[mask][i] = candidate
result = min(dp[(1 << n) - 1], key=len)
return result
dp
table.The optimal solution uses a greedy approach combined with dynamic programming to efficiently compute and combine strings based on their overlaps. This method significantly improves performance compared to the brute-force approach, especially for larger input sets.