[Swift]LeetCode943. 最短超级串 | Find the Shortest Superstring

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

➤微信公众号:山青咏芝(shanqingyongzhi)

➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/

➤GitHub地址:https://github.com/strengthen/LeetCode

➤原文地址:https://www.cnblogs.com/strengthen/p/10015724.html

➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。

➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

热烈欢迎,请直接点击!!!

进入博主App Store主页,下载使用各个作品!!!

注:博主将坚持每月上线一个新app!!!

Given an array A of strings, find any smallest string that contains each string in A as a substring.

We may assume that no string in A is substring of another string in A.

Example 1:

Input: ["alex","loves","leetcode"]
Output: "alexlovesleetcode"
Explanation: All permutations of "alex","loves","leetcode" would also be accepted.

Example 2:

Input: ["catg","ctaagt","gcta","ttca","atgcatc"]
Output: "gctaagttcatgcatc"

Note:

  1. 1 <= A.length <= 12
  2. 1 <= A[i].length <= 20

给定一个字符串数组 A,找到以 A 中每个字符串作为子字符串的最短字符串。

我们可以假设 A 中没有字符串是 A 中另一个字符串的子字符串。

示例 1:

输入:["alex","loves","leetcode"]
输出:"alexlovesleetcode"
解释:"alex","loves","leetcode" 的所有排列都会被接受。

示例 2:

输入:["catg","ctaagt","gcta","ttca","atgcatc"]
输出:"gctaagttcatgcatc"

提示:

  1. 1 <= A.length <= 12
  2. 1 <= A[i].length <= 20

100ms

 1 class Solution {
 2     func countSubstr(_ A: [String], _ n: String) -> Int {
 3       var sum = 0
 4       for var s in A {
 5         if n.contains(s) {
 6           sum += s.count
 7         }
 8       }
 9       return sum
10     }
11     func shortestSuperstring(_ Ain: [String]) -> String {
12         var A = Ain
13         while A.count > 1 {
14           var maxC = 0
15           var newStr = ""
16           for var i in 0..<A.count {
17             for var j in 0..<A.count {
18               guard i != j else {
19                 continue
20               } 
21               if A[i].count == 1 { continue }
22               for var l in 1...A[i].count-1 {
23                 if A[j].hasPrefix(A[i].suffix(l)) {
24                   let n = A[i] + A[j].suffix(A[j].count - l)
25                   let C = countSubstr(A, n) - n.count
26                   if C > maxC {
27                     maxC = C
28                     newStr = n
29                   }
30                 }
31               }
32             }
33           }
34           if maxC == 0 {
35             newStr = A[0] + A[1]
36           }
37           A.removeAll(where: { newStr.contains($0) })
38           A.append(newStr)
39         }
40         return A[0]
41     }
42 }
43 
44 extension String { 
45    func contains(_ find: String) -> Bool{
46      return self.range(of: find) != nil
47    }
48 }

364ms

  1 class Solution {
  2     func shortestSuperstring(_ A: [String]) -> String {
  3         var N:Int = A.count
  4         
  5         // Populate overlaps
  6         var overlaps:[[Int]] = [[Int]](repeating:[Int](repeating:0,count:N),count:N)
  7         for i in 0..<N
  8         {
  9             for j in 0..<N
 10             {
 11                 if i != j
 12                 {
 13                     var m:Int = min(A[i].count, A[j].count)
 14                     for k in (0...m).reversed()
 15                     {
 16                         if A[i].hasSuffix(A[j].substring(0, k))
 17                         {
 18                             overlaps[i][j] = k
 19                             break
 20                         }
 21                     }
 22                 }
 23             }
 24         }
 25         // dp[mask][i] = most overlap with mask, ending with ith element
 26         var dp:[[Int]] = [[Int]](repeating:[Int](repeating:0,count:N),count:1<<N)
 27         var parent:[[Int]] = [[Int]](repeating:[Int](repeating:-1,count:N),count:1<<N)
 28         for mask in 0..<(1<<N)
 29         {
 30             for bit in 0..<N
 31             {
 32                 if ((mask >> bit) & 1) > 0
 33                 {
 34                     // Let\'s try to find dp[mask][bit].  Previously, we had
 35                     // a collection of items represented by pmask.
 36                     var pmask:Int = mask ^ (1 << bit)
 37                     if pmask == 0 {continue}
 38                     for i in 0..<N
 39                     {
 40                         if ((pmask >> i) & 1) > 0
 41                         {
 42                             // For each bit i in pmask, calculate the value
 43                             // if we ended with word i, then added word \'bit\'.
 44                             var val:Int = dp[pmask][i] + overlaps[i][bit]
 45                             if val > dp[mask][bit]
 46                             {
 47                                 dp[mask][bit] = val
 48                                 parent[mask][bit] = i
 49                             }
 50                         }
 51                     }  
 52                 }
 53             }
 54         }
 55         // # Answer will have length sum(len(A[i]) for i) - max(dp[-1])
 56         // Reconstruct answer, first as a sequence \'perm\' representing
 57         // the indices of each word from left to right.
 58         var perm:[Int] = [Int](repeating:0,count:N)
 59         var seen:[Bool] = [Bool](repeating:false,count:N)
 60         var t:Int = 0
 61         var mask:Int = (1 << N) - 1
 62         
 63         // p: the last element of perm (last word written left to right)
 64         var p:Int = 0
 65         for j in 0..<N
 66         {
 67             if dp[(1<<N) - 1][j] > dp[(1<<N) - 1][p]
 68             {
 69                 p = j
 70             }
 71         }
 72         
 73         // Follow parents down backwards path that retains maximum overlap
 74         while (p != -1)
 75         {
 76             perm[t] = p
 77             t += 1
 78             seen[p] = true
 79             var p2:Int = parent[mask][p]
 80             mask ^= 1 << p
 81             p = p2
 82         }        
 83         
 84         // Reverse perm
 85         for i in 0..<(t/2)
 86         {
 87             var v:Int = perm[i]
 88             perm[i] = perm[t-1-i]
 89             perm[t-1-i] = v
 90         }
 91         
 92         // Fill in remaining words not yet added
 93         for i in 0..<N
 94         {
 95             if !seen[i]
 96             {
 97                 perm[t] = i
 98                 t += 1
 99             }
100         }
101         
102         // Reconstruct final answer given perm
103         var ans:String = String(A[perm[0]])
104         for i in 1..<N
105         {
106             var overlap:Int = overlaps[perm[i-1]][perm[i]]
107             ans.append(A[perm[i]].substring(overlap))
108         }
109         return ans
110     }
111 }
112 
113 extension String {    
114 // 截取字符串:从index到结束处
115     // - Parameter index: 开始索引
116     // - Returns: 子字符串
117     func substring(_ index: Int) -> String {
118         let theIndex = self.index(self.endIndex, offsetBy: index - self.count)
119         return String(self[theIndex..<endIndex])
120     }
121     
122     // 截取字符串:指定索引和字符数
123     // - begin: 开始截取处索引
124     // - count: 截取的字符数量
125     func substring(_ begin:Int,_ count:Int) -> String {
126         let start = self.index(self.startIndex, offsetBy: max(0, begin))
127         let end = self.index(self.startIndex, offsetBy:  min(self.count, begin + count))
128         return String(self[start..<end]) 
129     }
130 }