classSolution { public String shortestSuperstring(String[] A) { intN= A.length;
// Populate overlaps int[][] overlaps = newint[N][N]; for (inti=0; i < N; ++i) for (intj=0; j < N; ++j) if (i != j) { intm= Math.min(A[i].length(), A[j].length()); for (intk= m; k >= 0; --k) if (A[i].endsWith(A[j].substring(0, k))) { overlaps[i][j] = k; break; } }
// dp[mask][i] = most overlap with mask, ending with ith element int[][] dp = newint[1<<N][N]; int[][] parent = newint[1<<N][N]; for (intmask=0; mask < (1<<N); ++mask) { Arrays.fill(parent[mask], -1);
for (intbit=0; bit < N; ++bit) if (((mask >> bit) & 1) > 0) { // Let's try to find dp[mask][bit]. Previously, we had // a collection of items represented by pmask. intpmask= mask ^ (1 << bit); if (pmask == 0) continue; for (inti=0; i < N; ++i) if (((pmask >> i) & 1) > 0) { // For each bit i in pmask, calculate the value // if we ended with word i, then added word 'bit'. intval= dp[pmask][i] + overlaps[i][bit]; if (val > dp[mask][bit]) { dp[mask][bit] = val; parent[mask][bit] = i; } } } }
// # Answer will have length sum(len(A[i]) for i) - max(dp[-1]) // Reconstruct answer, first as a sequence 'perm' representing // the indices of each word from left to right.
// p: the last element of perm (last word written left to right) intp=0; for (intj=0; j < N; ++j) if (dp[(1<<N) - 1][j] > dp[(1<<N) - 1][p]) p = j;
// Follow parents down backwards path that retains maximum overlap while (p != -1) { perm[t++] = p; seen[p] = true; intp2= parent[mask][p]; mask ^= 1 << p; p = p2; }
// Reverse perm for (inti=0; i < t/2; ++i) { intv= perm[i]; perm[i] = perm[t-1-i]; perm[t-1-i] = v; }
// Fill in remaining words not yet added for (inti=0; i < N; ++i) if (!seen[i]) perm[t++] = i;
// Reconstruct final answer given perm StringBuilderans=newStringBuilder(A[perm[0]]); for (inti=1; i < N; ++i) { intoverlap= overlaps[perm[i-1]][perm[i]]; ans.append(A[perm[i]].substring(overlap)); }
classSolution(object): defshortestSuperstring(self, A): N = len(A)
# Populate overlaps overlaps = [[0] * N for _ in xrange(N)] for i, x inenumerate(A): for j, y inenumerate(A): if i != j: for ans in xrange(min(len(x), len(y)), -1, -1): if x.endswith(y[:ans]): overlaps[i][j] = ans break
# dp[mask][i] = most overlap with mask, ending with ith element dp = [[0] * N for _ in xrange(1<<N)] parent = [[None] * N for _ in xrange(1<<N)] for mask in xrange(1, 1 << N): for bit in xrange(N): if (mask >> bit) & 1: # Let's try to find dp[mask][bit]. Previously, we had # a collection of items represented by pmask. pmask = mask ^ (1 << bit) if pmask == 0: continue for i in xrange(N): if (pmask >> i) & 1: # For each bit i in pmask, calculate the value # if we ended with word i, then added word 'bit'. value = dp[pmask][i] + overlaps[i][bit] if value > dp[mask][bit]: dp[mask][bit] = value parent[mask][bit] = i
# Answer will have length sum(len(A[i]) for i) - max(dp[-1]) # Reconstruct answer:
# Follow parents down backwards path that retains maximum overlap perm = [] mask = (1<<N) - 1 i = max(xrange(N), key = dp[-1].__getitem__) while i isnotNone: perm.append(i) mask, i = mask ^ (1<<i), parent[mask][i]
# Reverse path to get forwards direction; add all remaining words perm = perm[::-1] seen = [False] * N for x in perm: seen[x] = True perm.extend([i for i in xrange(N) ifnot seen[i]])
# Reconstruct answer given perm = word indices in left to right order ans = [A[perm[0]]] for i in xrange(1, len(perm)): overlap = overlaps[perm[i-1]][perm[i]] ans.append(A[perm[i]][overlap:])
return"".join(ans)
复杂度分析
时间复杂度:O(N^2 * (2^N + W)),其中 N 是字符串的数目,W 是字符串的最大长度。