• (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;
        }
    };
  • 相关阅读:
    NC13950 Alliances(LCA)
    NC13884 Paint Box(容斥原理)
    Gym102174B 炼金术(AC自动机)
    CF301D Yaroslav and Divisors(树状数组)
    CF1443D Extreme Subtraction(思维)
    Gym102174L 旅行的意义(期望dp)
    Gym102220F Mini-game Before Contest(博弈论)
    Gym102220D Master of Data Structure (虚树)
    用random.simple来解决从0-99这100个数中随机取10个不重复的数
    一个栈的输入序列为1,2,3,4,5,则下列序列中不可能是栈的输出序列的是()
  • 原文地址:https://www.cnblogs.com/Bella2017/p/11359850.html
Copyright © 2020-2023  润新知