Given a wordlist
, we want to implement a spellchecker that converts a query word into a correct word.
For a given query
word, the spell checker handles two categories of spelling mistakes:
- Capitalization: If the query matches a word in the wordlist (case-insensitive), then the query word is returned with the same case as the case in the wordlist.
- Example:
wordlist = ["yellow"]
,query = "YellOw"
:correct = "yellow"
- Example:
wordlist = ["Yellow"]
,query = "yellow"
:correct = "Yellow"
- Example:
wordlist = ["yellow"]
,query = "yellow"
:correct = "yellow"
- Example:
- Vowel Errors: If after replacing the vowels (‘a‘, ‘e‘, ‘i‘, ‘o‘, ‘u‘) of the query word with any vowel individually, it matches a word in the wordlist (case-insensitive), then the query word is returned with the same case as the match in the wordlist.
- Example:
wordlist = ["YellOw"]
,query = "yollow"
:correct = "YellOw"
- Example:
wordlist = ["YellOw"]
,query = "yeellow"
:correct = ""
(no match) - Example:
wordlist = ["YellOw"]
,query = "yllw"
:correct = ""
(no match)
- Example:
In addition, the spell checker operates under the following precedence rules:
- When the query exactly matches a word in the wordlist (case-sensitive), you should return the same word back.
- When the query matches a word up to capitlization, you should return the first such match in the wordlist.
- When the query matches a word up to vowel errors, you should return the first such match in the wordlist.
- If the query has no matches in the wordlist, you should return the empty string.
Given some queries
, return a list of words answer
, where answer[i]
is the correct word for query = queries[i]
.
Example 1:
Input: wordlist = ["KiTe","kite","hare","Hare"], queries = ["kite","Kite","KiTe","Hare","HARE","Hear","hear","keti","keet","keto"] Output: ["kite","KiTe","KiTe","Hare","hare","","","KiTe","","KiTe"]
Note:
1 <= wordlist.length <= 5000
1 <= queries.length <= 5000
1 <= wordlist[i].length <= 7
1 <= queries[i].length <= 7
- All strings in
wordlist
andqueries
consist only of english letters.
踩坑踩了一个下午,掉到坑里出不来了。
Runtime: 96 ms, faster than 100.00% of C++ online submissions for Vowel Spellchecker.
第一种是我的做法 修改了TrieNode的结构,让它带了一个case_sensitive的标志位。如果带上大小写搜索,
每次需要判断字符的大小写,这样得到的是第一种准确的搜索。如果不敏感,就全部放在小写的这个节点里。
为了满足题意,大小写不敏感的可能有多种,那么Trie节点带一个数组比较合适。
注意:
1. 本来的字典可能有重复,我去。。。
2. 需要返回最小的index,那就把所有的求出来以后再求最小的index。
写了一个下午。
class TrieNode{ public: string word; vector<string> wordlist; TrieNode* lowercase[26]; TrieNode* uppercase[26]; TrieNode(){ for(int i=0; i<26; i++) lowercase[i] = nullptr; for(int i=0; i<26; i++) uppercase[i] = nullptr; } }; class Trie{ public: TrieNode* root; Trie(const vector<string>& wordlist, bool case_sensitive = true){ root = new TrieNode(); BuildTrie(wordlist, case_sensitive); } void BuildTrie(const vector<string>& wordlist, bool case_sensitive = true){ for(int i=0; i<wordlist.size(); i++){ TrieNode* tmp = root; for(int j=0; j<wordlist[i].size(); j++){ char tmpchar = wordlist[i][j]; int idx = 0; if(!case_sensitive){ if(tmpchar >= ‘A‘ && tmpchar <= ‘Z‘){ idx = tmpchar - ‘A‘; }else idx = tmpchar - ‘a‘; if(!tmp->lowercase[idx]) tmp->lowercase[idx] = new TrieNode(); tmp = tmp->lowercase[idx]; }else{ if(tmpchar >= ‘A‘ && tmpchar <= ‘Z‘){ idx = tmpchar - ‘A‘; if(!tmp->uppercase[idx]) tmp->uppercase[idx] = new TrieNode(); tmp = tmp->uppercase[idx]; }else { idx = tmpchar - ‘a‘; if(!tmp->lowercase[idx]) tmp->lowercase[idx] = new TrieNode(); tmp = tmp->lowercase[idx]; } } } if(case_sensitive){ tmp->word = wordlist[i]; }else { tmp->wordlist.push_back(wordlist[i]); } } } bool hasword(string word, string& foundword, bool case_sensitive = true){ TrieNode* tmp = root; locale loc; for(int i=0; i<word.size(); i++){ char tmpchar = word[i]; int idx = 0; if(!case_sensitive){ tmpchar = tolower(tmpchar, loc); idx = tmpchar - ‘a‘; if(!tmp->lowercase[idx]) return false; tmp = tmp->lowercase[idx]; }else { if(tmpchar >= ‘A‘ && tmpchar <= ‘Z‘) { idx = tmpchar - ‘A‘; if(!tmp->uppercase[idx]) return false; tmp = tmp->uppercase[idx]; } else { idx = tmpchar - ‘a‘; if(!tmp->lowercase[idx]) return false; tmp = tmp->lowercase[idx]; } } } if(!case_sensitive) { if(!tmp->wordlist.empty()){ foundword = tmp->wordlist[0]; return true; } return false; } if(!tmp->word.empty()) { foundword = tmp->word; return true; } return false; } }; class Solution { public: set<char> vset; unordered_map<string,int> mp; vector<string> spellchecker(vector<string>& wordlist, vector<string>& queries) { for(int i=0; i<wordlist.size(); i++){ mp[wordlist[i]] = i; } vset.insert(‘a‘);vset.insert(‘e‘);vset.insert(‘i‘); vset.insert(‘o‘);vset.insert(‘u‘); vector<string> ret; Trie trie_case_sensi = Trie(wordlist); Trie trie_not_case_sensi = Trie(wordlist, false); for(int i=0; i<queries.size(); i++){ string foundword; vector<string> foundwordvec; if(trie_case_sensi.hasword(queries[i],foundword)) { ret.push_back(queries[i]); }else if(trie_not_case_sensi.hasword(queries[i], foundword, false)){ ret.push_back(foundword); }else { dfs(trie_not_case_sensi.root, queries[i], foundwordvec, 0); int minidx = wordlist.size(); for(auto x : foundwordvec) minidx = min(minidx, mp[x]); if(minidx == wordlist.size()) ret.push_back(""); else ret.push_back(wordlist[minidx]); } } return ret; } void dfs(const TrieNode* root,string query, vector<string>& ret, int start){ if(start == query.size()){ assert(!root->wordlist.empty()); ret.push_back(root->wordlist[0]); return ; } std::locale loc; char c = tolower(query[start],loc); int idx = 0; idx = c - ‘a‘; if(vset.count(c)){ for(auto it = vset.begin(); it != vset.end(); it++){ char vsub = *it; int newidx = 0; newidx = vsub - ‘a‘; if(!root->lowercase[newidx]) continue; TrieNode* nextroot = root->lowercase[newidx]; dfs(nextroot, query, ret, start+1); } }else{ if(!root->lowercase[idx]) return ; TrieNode* nextroot = root->lowercase[idx]; dfs(nextroot, query, ret, start+1); } } };
下面看看网上的大神的解法,很简单,既然aeiou都能互相匹配,那就把aeiou变成#,这样一来不就行了么!真是厉害。
class Solution { public String[] spellchecker(String[] wordlist, String[] queries) { Set<String> words = new HashSet<>(Arrays.asList(wordlist)); HashMap<String, String> cap = new HashMap<>(); HashMap<String, String> vowel = new HashMap<>(); for (String w : wordlist) { String lower = w.toLowerCase(), devowel = lower.replaceAll("[aeiou]", "#"); cap.putIfAbsent(lower, w); vowel.putIfAbsent(devowel, w); } for (int i = 0; i < queries.length; ++i) { if (words.contains(queries[i])) continue; String lower = queries[i].toLowerCase(), devowel = lower.replaceAll("[aeiou]", "#"); if (cap.containsKey(lower)) { queries[i] = cap.get(lower); } else if (vowel.containsKey(devowel)) { queries[i] = vowel.get(devowel); } else { queries[i] = ""; } } return queries; } }
原文地址:https://www.cnblogs.com/ethanhong/p/10199989.html