原题链接在这里:https://leetcode.com/problems/replace-words/description/
题目:
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:
- The input will only have lower-case letters.
- 1 <= dict words number <= 1000
- 1 <= sentence words number <= 1000
- 1 <= root length <= 100
- 1 <= sentence words length <= 1000
题解:
利用Trie树. 把dict中每个词先放进Trie树中.
对于sentence按照空格拆分出的token, 从头添加token的char, 试验是否能在Trie树中找到. 找到说明加到这就是个root了, 可以返回.
若是Trie树中都没有starts with当前值时说明这个token 没有root, 返回原token.
Time Complexity: O(n*m + k*p). n = dict.size(). m是dict中单词平均长度. k是sentence中token个数. p是token平均长度.
Space: O(n*m+k).
AC Java:
1 class Solution { 2 public String replaceWords(List<String> dict, String sentence) { 3 if(sentence == null || sentence.length() == 0 || dict == null || dict.size() == 0){ 4 return sentence; 5 } 6 7 Trie trie = new Trie(); 8 for(String word : dict){ 9 trie.insert(word); 10 } 11 12 String [] tokens = sentence.split("\s+"); 13 14 StringBuilder sb = new StringBuilder(); 15 for(String token : tokens){ 16 sb.append(getRootOrDefault(token, trie) + " "); 17 } 18 19 sb.deleteCharAt(sb.length()-1); 20 return sb.toString(); 21 } 22 23 private String getRootOrDefault(String s, Trie trie){ 24 StringBuilder sb = new StringBuilder(); 25 for(int i = 0; i<s.length(); i++){ 26 sb.append(s.charAt(i)); 27 if(trie.search(sb.toString())){ 28 return sb.toString(); 29 }else if(!trie.startsWith(sb.toString())){ 30 return s; 31 } 32 } 33 return s; 34 } 35 } 36 37 class Trie{ 38 private TrieNode root; 39 40 public Trie(){ 41 root = new TrieNode(); 42 } 43 44 public void insert(String word){ 45 TrieNode p = root; 46 for(char c : word.toCharArray()){ 47 if(p.nexts[c-'a'] == null){ 48 p.nexts[c-'a'] = new TrieNode(); 49 } 50 p = p.nexts[c-'a']; 51 } 52 53 p.val = word; 54 } 55 56 public boolean search(String word){ 57 TrieNode p = root; 58 for(char c : word.toCharArray()){ 59 if(p.nexts[c-'a'] == null){ 60 return false; 61 } 62 p = p.nexts[c-'a']; 63 } 64 return p.val.equals(word); 65 } 66 67 public boolean startsWith(String word){ 68 TrieNode p = root; 69 for(char c : word.toCharArray()){ 70 if(p.nexts[c-'a'] == null){ 71 return false; 72 } 73 p = p.nexts[c-'a']; 74 } 75 return true; 76 } 77 } 78 79 class TrieNode{ 80 String val = ""; 81 TrieNode [] nexts; 82 83 public TrieNode(){ 84 nexts = new TrieNode[26]; 85 } 86 }
Another implementation.
1 class Solution { 2 public String replaceWords(List<String> dict, String sentence) { 3 if(sentence == null || sentence.length() == 0 || dict == null || dict.size() == 0){ 4 return sentence; 5 } 6 7 TrieNode root = new TrieNode(); 8 for(String word : dict){ 9 TrieNode p = root; 10 for(char c : word.toCharArray()){ 11 if(p.nexts[c-'a'] == null){ 12 p.nexts[c-'a'] = new TrieNode(); 13 } 14 15 p = p.nexts[c-'a']; 16 } 17 18 p.val = word; 19 } 20 21 String [] words = sentence.split("\s+"); 22 for(int i = 0; i<words.length; i++){ 23 TrieNode p = root; 24 for(char c : words[i].toCharArray()){ 25 if(p.nexts[c-'a'] == null || p.val != null){ 26 break; 27 } 28 29 p = p.nexts[c-'a']; 30 } 31 32 words[i] = (p.val == null) ? words[i] : p.val; 33 } 34 35 return String.join(" ", words); 36 } 37 } 38 39 class TrieNode{ 40 String val; 41 TrieNode [] nexts; 42 43 public TrieNode(){ 44 nexts = new TrieNode[26]; 45 } 46 }