字典树例题 LintCode623 · K步编辑

题目描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

题目分析

在这里插入图片描述
在这里插入图片描述

字母树

在这里插入图片描述

动态规划组成部分一:确定状态

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

动态规划组成部分三:初始条件和边界情况

在这里插入图片描述

动态规划组成部分四:计算顺序

在这里插入图片描述

Java代码实现

    char[] tar = null;
    int K = 0;
    int n = 0;
    List<String> res = null;

    public List<String> kDistance(String[] words, String target, int k) {
        tar = target.toCharArray();
        n = tar.length;
        K = k;
        res = new ArrayList<>();
        TrieNode root = new TrieNode();
        for (int i = 0; i < words.length; i++)
            root.insert(words[i]);
        int[] f = new int[n + 1];
        for (int i = 0; i <= n; i++)
            f[i] = i;
        dfs(root, f);
        return res;
    }

    private void dfs(TrieNode p, int[] f) {
        int[] nf = new int[n + 1];
        if (p.hasWord)
            if (f[n] <= K)
                res.add(p.word);
        for (int i = 0; i < 26; i++) {
            if (p.sons[i] == null)
                continue;
            nf[0] = f[0] + 1;
            for (int j = 1; j <= n; j++) {
                nf[j] = Math.min(Math.min(nf[j - 1] + 1, f[j] + 1), f[j - 1] + 1);
                if (i == tar[j - 1] - 'a')
                    nf[j] = Math.min(nf[j], f[j - 1]);
            }
            dfs(p.sons[i], nf);
        }
    }
}

class TrieNode {
    TrieNode[] sons;
    boolean hasWord;
    String word;

    public TrieNode() {
        sons = new TrieNode[26];
        for (int i = 0; i < 26; i++)
            sons[i] = null;
        hasWord = false;
    }

    public void insert(String wordStr) {
        char[] word = wordStr.toCharArray();
        int c;
        TrieNode p = this;
        for (int i = 0; i < word.length; i++) {
            c = word[i] - 'a';
            if (p.sons[c] == null)
                p.sons[c] = new TrieNode();
            p = p.sons[c];
        }
        p.hasWord = true;
        p.word = wordStr;
    }
}
代码解读

这个题目还是非常难的,这里对Java代码进行解读。
首先是声明了四个全局变量,之所以声明为全局变量是因为这是dfs每次进行搜索的时候需要用到的,如果将它们作为参数传入到dfs的 参数列表中则会使得dfs函数变得冗杂,所以最佳选择就是声明为全局变量。
然后是字典树TrieNode的定义,它的三个成员分为是TrieNode[] sons,boolean hasWord和String word,sons表示节点的孩子节点;hasWord则表示是不是给出的字符串,如果是true就表示该节点及祖先节点组成了一个待求的字符串,word就表示该字符串。insert函数则是用来将所有的待求字符串添加到root节点中。
最后说一下dfs函数,dfs函数有两个参数,TrieNode p和 int[] f,p即表示要深度优先搜索的当前节点,f则表示当前节点的前缀字符串(包括当前节点所代表的字符)与target字符串的编辑距离,如f[n]表示当前节点的前缀字符串与 target的前n个字符的编辑距离。
之所以要将数组f传入dfs函数参数列表,是因为这个数组f是在随着节点变化的,每个节点与target的编辑距离是不同的,而且在进行当前节点的f数组计算的时候需要用到父亲节点的f数组,所以要将f数组写的到参数列表传递给子节点使用。
nf[j] = Math.min(Math.min(nf[j - 1] + 1, f[j] + 1), f[j - 1] + 1);分别对应着编辑距离的增、删和改三种情况,画张图理解起来比较直观
在这里插入图片描述
新增是在当前已经加入了“a”的基础上新增,所以需要使用nf数组,即nf[j-1]+1。
在这里插入图片描述
删除了“a”之后,字符串与前缀字符出一样,所以使用的是f数组,即f[j]+1。
在这里插入图片描述
将“a”修改为“b”后,相当于将target字符串的最后一个字符“b”抵消掉,当前节点的“b”也被抵消掉,变成了前缀节点字符串,所以使用的是f数组,即f[j-1]+1。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值