十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Swift 实现最小编辑距离:基于 Levenshtein 距离的动态规划字符串相似度算法

Swift 实现最小编辑距离:基于 Levenshtein 距离的动态规划字符串相似度算法 示例工程教程【免费下载链接】swift-algorithm-clubAlgorithms and data structures in Swift, with explanations!项目地址https://gitcode.com/gh_mirrors/sw/swift-algorithm-club点击查看免费下载导读本文讲解 Swift Algorithm Club 仓库中 Minimum Edit Distance 模块的核心算法最小编辑距离Minimum Edit Distance。它通过统计将一个字符串变换为另一个字符串所需的最少单字符操作代价来衡量两个字符串的相似程度是拼写纠错、模糊匹配、DNA 序列比对等场景的基础。读完本文你将掌握 Levenshtein 距离的三种编辑操作及其代价模型、动态规划递推公式的推导过程并能直接运行仓库提供的 Swift 实现完成任意两个字符串的编辑距离计算。什么是最小编辑距离最小编辑距离Minimum Edit Distance是一种量化两个字符串w与u相似程度的方法它统计将w变换为u或反向变换所必需的单字符操作代价之和代价越小两个字符串越相似代价越大二者差异越大。以字符串Door与Dolls为例二者看似只有个别字符不同但编辑距离并非简单比较字符差异个数而是要看实际需要执行哪些编辑操作才能完成变换。这引出了下面要介绍的经典度量——Levenshtein 距离。Levenshtein 距离三种编辑操作与代价模型仓库文档明确采用的度量是Levenshtein 距离它允许三种单字符变换操作每种操作具有固定的代价操作记法含义代价插入 Insertionε→x插入单个符号x1删除 Deletionx→ε删除单个符号x1替换 Substitutionx→y将符号x替换为符号yx ≠ y时为 1x y时为 0注意替换操作在x y即两字符相同时代价为 0这保证了相同字符的对齐不产生任何代价是递推公式中对角线继承分支的依据。当通过一串操作序列完成字符串变换时各操作的代价累加即得到该序列的总代价而最小编辑距离就是所有可行序列中的最小总代价。示例从Door到Dolls文档给出了一个直观示例字符串Door可以通过以下三个操作变换为Dollso→l替换Door → Dlorr→l替换Dlor → Dlolε→s插入Dlol → Dolls三步操作各花费代价 1总计 3因此Door与Dolls的最小编辑距离为3。为什么需要动态规划避免指数级复杂度最直观的求解方式是枚举所有可能的操作序列但操作序列的组合爆炸会带来指数级时间复杂度这在字符串稍长时完全不可行。因此仓库文档采用经典的动态规划思路把原问题分解为前缀对前缀的子问题用一张二维矩阵缓存已经计算出的前缀最小编辑距离再自底向上逐格填充最终得到完整字符串之间的距离。每个格子的计算都只依赖前一行/前一列/左上角的少量已算结果彻底避免了重复计算。完整实现剖析仓库的核心实现位于 MinimumEditDistance.playground/Contents.swift它以String扩展的形式提供minimumEditDistance(other:)方法下面对照源码逐步解析行号与仓库文件一致。1. 定义与矩阵初始化extension String { public func minimumEditDistance(other: String) - Int { let m self.count let n other.count var matrix [[Int]](repeating: Int, count: m 1)假设w与u的长度分别为m和n则创建一个(m1) × (n1)的二维矩阵。多出的一行一列用于表示空前缀的情况matrix[i][j]存放w的前i个字符与u的前j个字符之间的最小编辑距离。随后进行初始化填充第一行与第一列// initialize matrix for index in 1...m { // the distance of any first string to an empty second string matrix[index][0] index } for index in 1...n { // the distance of any second string to an empty first string matrix[0][index] index }第一列matrix[i][0] i表示将w的前i个字符变为空字符串只能靠i次删除代价为i第一行matrix[0][j] j表示将空字符串变为u的前j个字符只能靠j次插入代价为j。这两行初始化是后续递推的边界条件缺一不可。2. 动态规划主循环// compute Levenshtein distance for (i, selfChar) in self.enumerated() { for (j, otherChar) in other.enumerated() { if otherChar selfChar { // substitution of equal symbols with cost 0 matrix[i 1][j 1] matrix[i][j] } else { // minimum of the cost of insertion, deletion, or substitution // added to the already computed costs in the corresponding cells matrix[i 1][j 1] Swift.min(matrix[i][j] 1, matrix[i 1][j] 1, matrix[i][j 1] 1) } } }主循环按行、列逐格填充每个格子对应三种候选来源对应三种操作的递推关系替换matrix[i][j] 1两字符不同代价 1若两字符相同则直接继承matrix[i][j]替换代价为 0插入matrix[i 1][j] 1表示在w侧插入一个字符以对齐u的第j个字符删除matrix[i][j 1] 1表示删除w的第i个字符。三个候选中取最小值即保证当前格记录的是前缀间的最小编辑距离。这里用Swift.min显式限定避免与String.min之类的潜在冲突属于实现细节上的严谨处理。3. 读取结果return matrix[m][n] } }全部格子填充完毕后右下角matrix[m][n]恰好对应两个完整字符串的最小编辑距离直接返回即可。4. 调用示例Door.minimumEditDistance(other: Dolls)Playground 文件末尾的这行调用会返回3与文档中手推示例的结果一致可作为验证实现正确性的最小用例。复杂度分析时间复杂度Θ(mn)。双层循环遍历(m1) × (n1)个格子每个格子仅做常数次比较与加法因此总时间与两个字符串长度的乘积成正比。空间复杂度O(mn)可由源码结构推断。实现显式维护了完整的(m1) × (n1)二维数组。若需进一步优化可以观察到递推只依赖当前行与上一行使用两行滚动数组即可将空间降至 O(min(m,n))不过那将牺牲回溯编辑路径的能力仓库当前实现以清晰易懂为首要目标完整保留了矩阵。值得说明的是文档原文以教学清晰性为首要目标与 Swift Algorithm Club 项目解释算法如何工作的定位一致参见 README.markdown并未追求空间上的极致优化。典型应用场景最小编辑距离在工程实践中用途广泛以下为算法领域的通用背景知识帮助理解其价值拼写纠错计算用户输入与词典候选词的编辑距离取距离最小的候选作为纠正建议模糊搜索 / 文本相似度在近似匹配、去重场景中衡量两个字符串的接近程度生物信息学DNA/蛋白质序列比对中衡量两条序列的差异替换可对应碱基突变插入与删除对应缺口gap自然语言处理词级或字级的编辑距离常作为特征参与文本分类、机器翻译评测等任务。这些场景共同的关键诉求正是本文所讲的以最少操作代价完成字符串变换Levenshtein 距离因此成为其中最通用的度量之一。如何在本地运行本模块以 Xcode Playground 形式组织无需编译整个项目即可体验打开仓库中的 MinimumEditDistance.playgroundXcode 10 / Swift 4.2 及以上版本可正常打开参见 README.markdown 的环境说明查看 Contents.swift其中定义了String.minimumEditDistance(other:)扩展方法修改文件末尾的调用参数例如改为kitten.minimumEditDistance(other: sitting)即可在侧边栏实时看到计算结果经典用例kitten → sitting的编辑距离为 3可作为第二个自测用例。由于实现是一个纯 Swift 标准库的String扩展你也可以直接把这 30 余行代码复制到自己的项目或 Swift 脚本中独立使用。结语最小编辑距离通过三种单字符操作 代价累加的模型把字符串相似度问题转化为可计算的数值而 Levenshtein 距离加上动态规划的矩阵递推将指数级暴力枚举压缩为 Θ(mn) 的多项式时间求解。本文以仓库 Minimum Edit Distance 文档 为主线、以 Playground 实现 为佐证完整还原了从代价模型、初始化、递推填充到结果读取的每一步。文档末尾留下的TODO: 其他距离度量如 Damerau-Levenshtein、Hamming 距离等也为感兴趣的读者指出了进一步探索的方向——它们大多可以基于同样的动态规划框架扩展而来。赞分享示例工程教程【免费下载链接】swift-algorithm-clubAlgorithms and data structures in Swift, with explanations!项目地址https://gitcode.com/gh_mirrors/sw/swift-algorithm-club点击查看免费下载相关推荐Hello 算法编辑距离Levenshtein 距离动态规划解法全解析Hello 算法编辑距离Levenshtein 距离动态规划解法全解析 编辑距离Edit Distance又称 Levenshtein 距离是计算教程文档示例工程教育字符串相似度计算Learn-Algorithms中的编辑距离字符串相似度计算Learn Algorithms中的编辑距离 在日常工作中你是否曾遇到过需要比较两个字符串相似程度的场景比如搜索引擎的关键词纠错、论文查重教程Hello 算法编辑距离Levenshtein 距离动态规划详解与空间优化实战Hello 算法编辑距离Levenshtein 距离动态规划详解与空间优化实战 编辑距离Edit Distance又称莱文斯坦距离Levensht教程文档示例工程教育创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表