(Trie + DP) 623. K Edit Distance
思路:前缀树来存储字符串的所有前缀。
1. 状态转移方程:
2. 计算顺序
class Solution { public: /** * @param words: a set of stirngs * @param target: a target string * @param k: An integer * @return: output all the strings that meet the requirements */ struct TrieNode{ TrieNode* child[26]; bool is_word; string str; TrieNode(): is_word(false), str(""){ for(auto& a:child) a = NULL; } ~TrieNode(){ delete[] child; } }; struct Trie{ TrieNode* root = new TrieNode(); void insert(string word){ TrieNode* p = root; for(char a: word){ int i = a - 'a'; if(!p->child[i]) p->child[i] = new TrieNode(); p = p->child[i]; } p->is_word = true; p->str = word; } }; //at node p, prefix Sp //f means f[Sp][0~n] //todo: Sp -> (Sp,'a')...(Sp,'z') 推导从Sp到更长的前缀 void dfs(TrieNode* p, vector<int>& f, vector<string>& res, string& target, int k){ int n = target.size(); vector<int> nf(n+1, 0); //新的f //whether p has word if(p->is_word && f[n] <= k){ //p是一个完整的单词 res.push_back(p->str); } //f[Sp][j]:一个前缀Sp和Target前j个字符的最小编辑距离 //f[i][0] = i //f[0] = f[Sp][0] = |Sp| nf[0] = f[0] + 1; for(int i=0;i<26; i++){ //next char is i if(p->child[i] == NULL) continue; //拓展它的儿子 for(int j=1; j<=n; j++){ //f[i][j] = min( f[i][j-1]+1), f[i-1][j]+1, f[i-1][j-1]+1 nf[j] = min(min(nf[j-1]+1, f[j]+1), f[j-1]+1); int c = target[j-1] - 'a'; if(c == i){ //f[i][j] = min(f[i][j], f[i-1][j-1]), when A[i-1]==target[j-1] nf[j] = min(nf[j], f[j-1]); } } dfs(p->child[i], nf, res, target, k); } } vector<string> kDistance(vector<string> &words, string &target, int k) { // write your code here int n = target.size(); vector<int> f(n+1,0); vector<string> result; //init Trie Trie trie; for(string& word: words){ trie.insert(word); } TrieNode * p = trie.root; //init f //f[""][0~n] 前缀为空串时与Target的前n+1个字符的最小编辑距离 for(int i=0; i<=n; i++){ f[i] = i; } //dfs dfs(p, f, result, target, k); //return result return result; } };