class Solution: def shortestSuperstring(self, words: List[str]) -> str: N, MAX = len(words), float("inf") state = 1 << N dp = [[[MAX, ""] for _ in range (N)] for _ in range (state)] for i in range (N): dp[1 << i][i] = [len(words[i]), words[i]] for bitmask in range (1, state): for i in range (N): # Consider i as the last bit if bitmask & (1 << i) == 0: continue # Consider all previous state that can create i smallestCand = [MAX, ""] for j in range (N): if j != i and bitmask & (1 << j): cand = self.mergeWords(dp[bitmask ^ (1 << i)][j][1], words[i]) smallestCand = min(smallestCand, [len(cand), cand]) if smallestCand[0] != MAX: dp[bitmask][i] = smallestCand return min(dp[state - 1])[1] def mergeWords(self, word1, word2): if not word1: return word2 N, M = len(word1), len(word2) for i in range(M, 0, -1): if N - i >= 0 and word1[-i:] == word2[:i]: return word1 + word2[i:] return word1 + word2