[Swift]LeetCode648. 单词替换 | Replace Words

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:https://www.cnblogs.com/strengthen/p/10485210.html 
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

In English, we have a concept called root, which can be followed by some other words to form another longer word - let's call this word successor. For example, the root an, followed by other, which can form another word another.

Now, given a dictionary consisting of many roots and a sentence. You need to replace all the successor in the sentence with the root forming it. If a successor has many roots can form it, replace it with the root with the shortest length.

You need to output the sentence after the replacement.

Example 1:

Input: dict = ["cat", "bat", "rat"]
sentence = "the cattle was rattled by the battery"
Output: "the cat was rat by the bat" 

Note:

  1. The input will only have lower-case letters.
  2. 1 <= dict words number <= 1000
  3. 1 <= sentence words number <= 1000
  4. 1 <= root length <= 100
  5. 1 <= sentence words length <= 1000

在英语中,我们有一个叫做 词根(root)的概念,它可以跟着其他一些词组成另一个较长的单词——我们称这个词为 继承词(successor)。例如,词根an,跟随着单词 other(其他),可以形成新的单词 another(另一个)。

现在,给定一个由许多词根组成的词典和一个句子。你需要将句子中的所有继承词词根替换掉。如果继承词有许多可以形成它的词根,则用最短的词根替换它。

你需要输出替换之后的句子。

示例 1:

输入: dict(词典) = ["cat", "bat", "rat"]
sentence(句子) = "the cattle was rattled by the battery"
输出: "the cat was rat by the bat"

注:

  1. 输入只包含小写字母。
  2. 1 <= 字典单词数 <=1000
  3. 1 <=  句中词语数 <= 1000
  4. 1 <= 词根长度 <= 100
  5. 1 <= 句中词语长度 <= 1000

448ms

 1 class Solution {
 2     
 3     private let trie = Trie()
 4     
 5     func replaceWords(_ dict: [String], _ sentence: String) -> String {
 6         dict.forEach { word in
 7             trie.insert(word)
 8         }
 9         
10         var words = [String]()
11         sentence.split(separator: " ").forEach { word in
12             words.append(trie.replacement(String(word)))
13         }
14         return words.joined(separator: " ")
15     }    
16 }
17 
18 class Trie {
19     
20     private let root = TrieNode()
21     
22     func insert(_ word: String) {
23         var node = root
24         word.forEach { c in
25             let next = node.insert(c)
26             node = next
27         }
28         node.len = word.count
29     }
30     
31     func replacement(_ word: String) -> String {
32         var replace = ""
33         var node = root
34         for c in word {
35             guard let next = node.search(c) else {
36                 break
37             }
38             replace += String(c)
39             if next.len > 0 {
40                 return replace
41             }
42             node = next
43         }
44         return word
45     }    
46 }
47 
48 class TrieNode {
49     
50     var len = 0
51     private var map = [Character: TrieNode]()
52     
53     func search(_ c: Character) -> TrieNode? {
54         return map[c]
55     }
56     
57     func insert(_ c: Character) -> TrieNode {
58         if let node = map[c] {
59             return node
60         }
61         let node = TrieNode()
62         map[c] = node
63         return node
64     }    
65 }

532ms

 1 class Solution {
 2     func replaceWords(_ dict: [String], _ sentence: String) -> String {
 3         var trie = Trie()
 4         
 5         for word in dict {
 6             trie.insert(word)
 7         }
 8         
 9         var arr = sentence.split(separator: Character(" "))
10         var res = [String]()
11         for word in arr {
12             res.append(trie.searchForAbbr(String(word)))
13         }
14         return res.joined(separator: " ")
15     }
16 }
17 
18 class Trie {
19     class TrieNode: CustomStringConvertible {
20         var description: String {
21             return "(char) children: (children.keys)"
22         }
23         
24         var char: Character = Character(" ")
25         var isWordEnding: Bool = false
26         var children: [Character: TrieNode] = [Character: TrieNode]()
27         
28         init(char: Character = " ", isWordEnding: Bool = false, children: [Character: TrieNode] = [:]) {
29             self.char = char
30             self.isWordEnding = isWordEnding
31             self.children = children
32         }
33     }
34     var root: TrieNode
35     /** Initialize your data structure here. */
36     init() {
37         root = TrieNode()
38     }
39     func searchForAbbr(_ word: String) -> String {
40         var str = ""
41         var cur = root
42         for (index,c) in word.enumerated() {
43             str = str + String(c)
44             if cur.children[c] == nil {
45                 return word
46             } else {
47                 let next = cur.children[c]!
48                 if(next.isWordEnding) {
49                     return str
50                 }
51                 cur = next
52             }
53         }
54         return word
55     }
56     /** Inserts a word into the trie. */
57     func insert(_ word: String) {
58         var cur = root
59         for (index, c) in word.enumerated() {
60             if cur.children[c] == nil {
61                 cur.children[c] = TrieNode(char: c, isWordEnding: index == word.count - 1 , children: [:])
62             } else {
63                 if index == word.count - 1 {
64                     cur.children[c]!.isWordEnding = true
65                 }
66             }
67             cur = cur.children[c]!
68         }
69     }
70     
71     /** Returns if the word is in the trie. */
72     func search(_ word: String) -> TrieNode? {
73         var cur = root
74         
75         for c in word {
76             if cur.children[c] == nil {
77                 return nil
78             } else {
79                 let next = cur.children[c]!
80                 cur = next
81             }
82         }
83         return cur
84     }
85     
86     /** Returns if there is any word in the trie that starts with the given prefix. */
87     func startsWith(_ prefix: String) -> Bool {
88         var cur = root
89         for c in prefix {
90             if cur.children[c] == nil {
91                 return false
92             }
93             cur = cur.children[c]!
94         }
95         return true
96     }
97 }

544ms

 1 class Solution {
 2     class TrieNode {
 3         var terminal = false
 4         var children = [Character: TrieNode]()
 5     }
 6     
 7     class Trie {
 8         var root = TrieNode()
 9 
10         func addWord(_ word: String) {
11             var n = root
12             for ch in word.characters {
13                 if let child = n.children[ch] {
14                     n = child
15                 } else {
16                     let newNode = TrieNode()
17                     n.children[ch] = newNode
18                     n = newNode
19                 }
20             }
21             n.terminal = true
22         }
23         
24         func getWordRoot(_ word: String) -> String {
25             var n = root
26             let arr = Array(word.characters)
27             for i in 0..<arr.count {
28                 guard let child = n.children[arr[i]] else { return word }
29                 n = child
30                 if n.terminal {
31                     return String(arr[...i])
32                 }
33             }
34             return word
35         }
36     }
37     
38     func replaceWords(_ dict: [String], _ sentence: String) -> String {
39         let trie = Trie()
40         dict.forEach{ trie.addWord($0) }
41         
42         let words = Array(sentence.components(separatedBy: " "))
43         return words.map{ trie.getWordRoot($0) }.joined(separator: " ")
44     }
45 }

Runtime: 548 ms
Memory Usage: 22.9 MB
 1 class Solution {
 2     func replaceWords(_ dict: [String], _ sentence: String) -> String {
 3         var dict = dict
 4         var res:String = String()
 5         var t:String = String()
 6         var v:[[String]] = [[String]](repeating:[String](),count:26)
 7         var arr:[String] = sentence.components(separatedBy:" ")
 8         dict = dict.sorted { $0.count < $1.count }
 9         for word in dict
10         {
11             v[word[0].ascii - 97].append(word)
12         }
13         for str in arr
14         {
15             t = str
16             for word in v[t[0].ascii - 97]
17             {
18                 if t.subString(0, word.count) == word
19                 {
20                     t = word
21                     break
22                 }
23             }
24             res += t + " "
25         }
26         res.removeLast()
27         return res
28     }
29 }
30 
31 //String扩展
32 extension String {        
33     //subscript函数可以检索数组中的值
34     //直接按照索引方式截取指定索引的字符
35     subscript (_ i: Int) -> Character {
36         //读取字符
37         get {return self[index(startIndex, offsetBy: i)]}
38     }
39     
40     // 截取字符串:指定索引和字符数
41     // - begin: 开始截取处索引
42     // - count: 截取的字符数量
43     func subString(_ begin:Int,_ count:Int) -> String {
44         let start = self.index(self.startIndex, offsetBy: max(0, begin))
45         let end = self.index(self.startIndex, offsetBy:  min(self.count, begin + count))
46         return String(self[start..<end]) 
47     }
48 }
49 
50 //Character扩展 
51 extension Character  
52 {  
53   //Character转ASCII整数值(定义小写为整数值)
54    var ascii: Int {
55        get {
56            return Int(self.unicodeScalars.first?.value ?? 0)
57        }       
58     }    
59 }

568ms

 1 class Solution {
 2     class Node {
 3         var value: Character?
 4         var children: [Character : Node] = [:]
 5         var isTerminating = false
 6         
 7         init(value: Character? = nil) {
 8             self.value = value
 9         }
10         
11         func add(_ letter: Character) {
12             guard children[letter] == nil else { return }
13             children[letter] = Node(value: letter)
14         }
15     }
16     
17     var root = Node()
18     
19     func addWord(_ word: String) {
20         guard !word.isEmpty else { return }
21         
22         var currentNode = root
23         
24         for letter in word {
25             if currentNode.children[letter] == nil {
26                 currentNode.add(letter)
27             }
28             
29             guard let node = currentNode.children[letter] else { continue }
30             currentNode = node
31         }
32         
33         currentNode.isTerminating = true
34     }
35     
36     func findRoot(_ word: String) -> String? {
37         var result = ""
38         var currentNode = root
39         
40         for letter in word {
41             if let node = currentNode.children[letter] {
42                 currentNode = node
43                 if let value = node.value {
44                      result += String(value)
45                 }
46                 
47                 if currentNode.isTerminating {
48                     return result
49                 }
50             } else {
51                 if currentNode.isTerminating {
52                     return result
53                 } else {
54                     return nil
55                 }
56             }
57         }
58         
59         return result.isEmpty ? nil : result
60     }
61     
62     func replaceWords(_ dict: [String], _ sentence: String) -> String {
63         var result = ""
64         
65         for word in dict {
66             addWord(word)
67         }
68         
69         var currentWord = ""
70         
71         for char in sentence {
72             if char == " " {
73                 result += (findRoot(currentWord) ?? currentWord) + " "
74                 currentWord = ""   
75             } else {
76                 currentWord += String(char)
77             }
78         }
79         
80         result += findRoot(currentWord) ?? currentWord
81         return result
82     }
83 }

632ms

 1 class Solution {
 2     class TrieNode<Key : Hashable>{
 3     public var key : Key?
 4     public var isTerminating : Bool = false
 5     public var children : [Key : TrieNode] = [:]
 6     public init(_ key : Key?){
 7         self.key = key
 8     }
 9 }
10 
11 func replaceWords(_ dict: [String], _ sentence: String) -> String {
12     let trie = Trie<String>.init()
13     for str in dict{
14         trie.insert(str)
15     }
16     var results : [String] = []
17     let components = sentence.components(separatedBy: " ")
18     for component in components{
19         if let replacement = trie.findPrefixesWithCollection(component, prefix: ""){
20             results.append(replacement)
21         }else{
22             results.append(component)
23         }
24     }
25     
26     return results.joined(separator: " ")
27 }
28 
29 class Trie<CollectionType : RangeReplaceableCollection> where CollectionType.Element : Hashable{
30     public typealias Node = TrieNode<CollectionType.Element>
31     private let root = Node.init(nil)
32     public init(){}
33     
34     // Insertion
35     public func insert(_ collection : CollectionType){
36         var current = root
37         for element in collection{
38             if current.children[element] == nil{
39                 current.children[element] = Node.init(element)
40             }
41             current = current.children[element]!
42         }
43         current.isTerminating = true
44     }
45     
46     public func findPrefixesWithCollection(_ collection : CollectionType, prefix : CollectionType)->CollectionType?{
47         var current = root
48         var result = prefix
49         
50         for element in collection{
51             if current.isTerminating == true{
52                 break
53             }else{
54                 if current.children[element] == nil{
55                     return nil
56                 }else{
57                     result.append(element)
58                     current = current.children[element]!
59                 }
60             }
61         }
62         // now we have gotten the shortest word
63         return result
64     }
65   }
66 }

692ms

 1 class Solution {
 2     func replaceWords(_ dict: [String], _ sentence: String) -> String {
 3         let trie = Trie()
 4         for root in dict {
 5             trie.insert(root)
 6         }
 7         
 8         var retval: [String] = []
 9         let words = sentence.components(separatedBy: " ")
10         for word in words {
11             retval.append(trie.startsWith(word) ?? word)
12         }
13         return retval.joined(separator: " ")
14     }
15 }
16 
17 
18 
19 class TrieNode {
20     var key: Character?
21     var children: [Character: TrieNode] = [:]
22     var isTerminator = false
23     
24     init() {
25     }
26     
27     init(_ key: Character) {
28         self.key = key
29     }
30 }
31 
32 
33 class Trie {
34     private let root: TrieNode 
35     /** Initialize your data structure here. */
36     init() {
37         root = TrieNode()
38     }
39     
40     /** Inserts a word into the trie. */
41     func insert(_ word: String) {
42         var node = root
43         for char in word {
44             if let some = node.children[char] {
45                 node = some
46             } else {
47                 let n = TrieNode(char)
48                 node.children[char] = n
49                 node = n
50             }
51         }
52         node.isTerminator = true
53     }
54     
55     /** Returns if there is any word in the trie that starts with the given prefix. */
56     func startsWith(_ prefix: String) -> String? {
57       var retVal = ""
58       var node = root
59         for char in prefix {
60             if let some = node.children[char] {
61                 node = some
62                 retVal.append(node.key!)
63                 if node.isTerminator {
64                     return retVal
65                 }
66             } else {
67                 return nil
68             }
69         }
70         return retVal
71     }
72 }
原文地址:https://www.cnblogs.com/strengthen/p/10485210.html