• 编辑距离(Minimum Edit Distance)


    编辑距离(Minimum Edit Distance,MED),也叫 Levenshtein Distance。他的含义是计算字符串a转换为字符串b的最少单字符编辑次数。编辑操作有:插入、删除、替换(都是对a进行的变换)。用lev(i, j) 表示 a的前i个单词和 b的前j个单词的最短编辑距离(即从后往前)。可以分为以下几种情况:

    • i == 0j == 0
      • (lev(i, j) = max(i, j))
    • i,j 不为0, 且 (a[i] == a[j])
      • (lev(i, j) = lev(i-1, j-1))
    • i,j 不为0, 且 (a[i] != a[j])
      • 插入: (lev(i, j-1))
      • 删除: (lev(i-1, j))
      • 替换: (lev(i-1, j-1) + 1)
      • 三者取最小

    这里的插入是在 a[i] 后方插入,这样,b[j] 已经和 a[i] 后方的元素匹配,所以j前移;删除表示删除当前元素,a[i] 前面的元素顶上来,所以i前移,但是顶上来的元素不一定和j匹配,所以j不动。

    C++ 实现

    解法就是动态规划:

    class Solution {
    public:
    	vector<vector<int>> matrix;
    	int editDistance(string str1, string str2) {
    		int len1 = str1.size(); 
    		int len2 = str2.size();
    
    		matrix = vector<vector<int>>(len1 + 1, vector<int>(len2 + 1, 0));
    
    		for (int i = 0; i <= len1; ++i)
    			matrix[i][0] = i;
    
    		for (int j = 1; j <= len2; ++j)
    			matrix[0][j] = j;
    
    		for (int i = 1; i <= len1; ++i) {
    			for (int j = 1; j <= len2; ++j) {
    				if (str1[i] == str2[j])		matrix[i][j] = matrix[i - 1][j - 1];	// 最后一个字母相同
    				else {
    					int insert = matrix[i][j - 1] + 1;		// 插入
    					int del = matrix[i - 1][j] + 1;			// 删除
    					int replace = matrix[i - 1][j - 1] + 1;	// 替换
    					matrix[i][j] = min(insert, min(del, replace));
    				}
    			}
    		}
    		return matrix[len1][len2];
    	}
    };
    

    python-Levenshtein 库

    pip install python-Levenshtein

    import Levenshtein
    print(Levenshtein.distance("the","teh"))
    

    单词纠错

    前几天看到一个很有意思的代码,通过统计的方式,计算最后可能的单词。w是输入单词,c是可能的正确单词。根据贝叶斯,按照惯例忽略分母。

    [p(c | w)=frac{p(c) * p(w | c)}{p(w)} ]

    • (p(w|c)) : 计算通过w所有编辑距离为i的所有正确单词(就是c),i越小表示p越大
    • (p(c)) : 在上面的c中,找出频率最高的单词
    import re
    from collections import Counter
    
    def words(text): return re.findall(r'w+', text.lower())
    
    WORDS = Counter(words(open('big.txt').read()))
    
    def P(word, N=sum(WORDS.values())): 
        # 返回单词的概率
        return WORDS[word] / N
    
    def correction(word): 
        # 找到频率最高的c
        return max(candidates(word), key=P)
    
    def candidates(word): 
        '''
        找到候选单词c
        '''
        return (known([word]) or known(edits1(word)) or known(edits2(word)) or [word])
    
    def known(words): 
        # 返回 words 和 WORDS的交集. 找出正确单词
        return set(w for w in words if w in WORDS)
    
    def edits1(word):
        # 编辑距离为1的所有单词
        "All edits that are one edit away from `word`."
        letters    = 'abcdefghijklmnopqrstuvwxyz'
        splits     = [(word[:i], word[i:])    for i in range(len(word) + 1)]
        deletes    = [L + R[1:]               for L, R in splits if R]
        transposes = [L + R[1] + R[0] + R[2:] for L, R in splits if len(R)>1]
        replaces   = [L + c + R[1:]           for L, R in splits if R for c in letters]
        inserts    = [L + c + R               for L, R in splits for c in letters]
        return set(deletes + transposes + replaces + inserts)
    
    def edits2(word): 
        # 编辑距离为2的所有单词
        return (e2 for e1 in edits1(word) for e2 in edits1(e1))
    

    在python中 list1 or list2 的含义是:

    • 如果list1不为空,那么返回list1
    • 如果list1为空,那么返回list2

    所以这行代码的意思是:

    return (known([word]) or known(edits1(word)) or known(edits2(word)) or [word])
    
    • 如果单词是正确的就直接返回
    • 如果但是错的,就返回编辑距离是1的所有正确单词作为候选词
    • 如果编辑距离是1的正确单词没有,就返回编辑距离是2的所有正确单词作为候选词
    • 如果还是为空,就返回他自己
  • 相关阅读:
    GIT的使用及心得
    XCODE的演变及使用经验分享
    软件工程学习计划
    这只是一个测试,注意,这只是一个测试
    软工实践---个人
    调研Android开发环境的发展演变
    软件工程的实践项目的自我目标
    调研ANDRIOD平台的开发环境的发展演变
    软件工程的实践项目的自我目标
    Leetcode题库——39.组合总和
  • 原文地址:https://www.cnblogs.com/twilight0402/p/13384488.html
Copyright © 2020-2023  润新知