Skip to main content

Command Palette

Search for a command to run...

Solving Leetcode Interviews in Seconds with AI: Find the Shortest Superstring

Updated
3 min read

Introduction

In this blog post, we will explore how to solve the LeetCode problem "943" using AI. LeetCode is a popular platform for preparing for coding interviews, and with the help of AI tools like Chatmagic, we can generate solutions quickly and efficiently - helping you pass the interviews and get the job offer without having to study for months.

Problem Statement

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" Constraints: 1 <= words.length <= 12 1 <= words[i].length <= 20 words[i] consists of lowercase English letters. All the strings of words are unique.

Explanation

Here's a breakdown of the approach and the Python code:

  • High-Level Approach:

    • Calculate the overlap (prefix/suffix matching) between all pairs of words. This overlap information is stored in a matrix.
    • Use dynamic programming (with bitmasking) to find the shortest string that includes all words. The bitmask represents which words have been included so far.
    • Reconstruct the shortest string by backtracking through the DP table.
  • Complexity:

    • Runtime: O(n2 * 2n), where n is the number of words.
    • Storage: O(n * 2n)

Code

    def shortest_superstring(words):
    n = len(words)

    # Calculate overlaps
    overlaps = [[0] * n for _ in range(n)]
    for i in range(n):
        for j in range(n):
            if i != j:
                for k in range(min(len(words[i]), len(words[j])), -1, -1):
                    if words[i].endswith(words[j][:k]):
                        overlaps[i][j] = k
                        break

    # DP: dp[mask][i] is the shortest string covering words represented by mask, ending with word i
    dp = [[""] * n for _ in range(1 << n)]
    parent = [[0] * n for _ in range(1 << n)]  # Store parent word for backtracking

    # Initialize base cases: single words
    for i in range(n):
        dp[1 << i][i] = words[i]

    # Iterate through all possible subsets of words
    for mask in range(1, 1 << n):
        for i in range(n):
            if (mask & (1 << i)) != 0:  # If word i is in the subset
                for j in range(n):
                    if i != j and (mask & (1 << j)) != 0:  # If word j is also in the subset and not the same as i
                        new_string = dp[mask ^ (1 << i)][j] + words[i][overlaps[j][i]:]
                        if dp[mask][i] == "" or len(new_string) < len(dp[mask][i]):
                            dp[mask][i] = new_string
                            parent[mask][i] = j

    # Find the shortest string among all possible ending words
    min_len = float('inf')
    last_word = -1
    for i in range(n):
        if len(dp[(1 << n) - 1][i]) > 0 and len(dp[(1 << n) - 1][i]) < min_len:
            min_len = len(dp[(1 << n) - 1][i])
            last_word = i

    # Reconstruct the shortest superstring by backtracking
    result = ""
    mask = (1 << n) - 1
    while mask > 0:
        result = dp[mask][last_word]
        temp = last_word
        last_word = parent[mask][last_word]
        mask ^= (1 << temp)

    return result

More from this blog

C

Chatmagic blog

2894 posts