拼写错误纠正是所有电商网站或者搜索网站的核心,下面我们就来看看拼写纠错中常用到的算法,也就是我们的编辑距离了,也就是计算两个字符串之间的编辑距离。就是通过多少种操作才能将我们的输入单词给转换成我们的目标单词。这里的操作就是insert、delete、replace。这里每一个操作的话的成本都是1,要是两个单词之间的成本越小,那么就说明它们之间的距离就是越小的,长得更加的类似了。
一、暴力法求解伪代码
best_editDist = 一个非常大的数
for word in 词典:
best_editDist = min(editDist(word, target),best_editDist)
return best_editDist
但是暴力法有个问题,这里就是我们的词典的词数可能是106这么,时间复杂度就是O(106)了。这个时候找到最好的编辑距离的时候,就存在时间复杂度的问题了。
二、动态规划求解编辑距离
明确是DP问题之后,我们就需要定义何为状态,何为状态转移方程。比如说计算horse和ros之间的编辑距离dp,使用dp[m][n]来表示输入单词长度为n和m的编辑距离
状态:dp[i][j]表示的就是表示 word1 的前 i 个字母和 word2 的前 j 个字母之间的编辑距离。也就是我们的子问题了,下面就需要将这个问题的递归公式给写出来
状态转移方程:
- 当两个子串的最后一个字母相同的时候
2)当两个子串的最后一个字母不相同的时候
用LeetCode上面的一张图最好看了:
class Solution:
def minDistance(self, word1: str, word2: str) -> int:
# m和n分别是word1和word2之间的长度
m, n = len(word1), len(word2)
# 建立(m+1)*(m+1)的矩阵
dp =[[0 for _ in range(n+1)] for _ in range(m+1)]
for i in range(m+1):
for j in range(n+1):
# 假设第一个字符串为空,那么转换的代价就为j了
if(i==0):
dp[i][j]=j
# 假设第二个字符串为空,那么转换的代价就为i了
elif(j==0):
dp[i][j]=i
# 要是最后一个字符都是相同的,就不会产生代价
elif(word1[i-1]==word2[j-1]):
dp[i][j]=dp[i-1][j-1]
else:
# 要是最后一个字符不是相同的,则按照状态转移方程来写
dp[i][j]=1+min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1])
return dp[m][n]
时间复杂度:O(mn)
空间复杂度:O(mn)
参考资料:
1、https://leetcode-cn.com/problems/edit-distance/solution/bian-ji-ju-chi-by-leetcode/
2、