Sweet Snippet 之 字符串编辑距离

2024-04-12 21:08

本文主要是介绍Sweet Snippet 之 字符串编辑距离,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

字符串编辑距离的简单实现

字符串编辑距离应该是动态规划中的代表问题了:

给定两个字符串 a a a b b b,求解将 a a a 编辑 b b b 的操作步数(距离),编辑包含以下两种操作:

  • 删除某一字符
  • 增加某一字符

(这里我们不允许变更某一字符,注意一下)

求解方法则是根据子问题的结果"递推"出原问题的结果:

设字符串 a a a 的长度为 m m m, 字符串 b b b 的长度为 n n n, 我们定义问题 C ( i , j ) C(i, j) C(i,j)

C ( i , j ) C(i, j) C(i,j) : a a a 的(前缀)子串(长度为 i i i) 与 b b b 的(前缀)子串(长度为 j j j) 的字符串编辑距离.

接着就是 C ( i , j ) C(i, j) C(i,j) 的递推公式了(这里就不做细节的讲述了,不熟悉的朋友可以参考进一步的资料)

C ( i , j ) = { i , i f j = 0 j , i f i = 0 C ( i − 1 , j − 1 ) , i f a [ i ] = b [ j ] m i n ( C ( i − 1 , j ) , C ( i , j − 1 ) ) + 1 , o t h e r w i s e C(i, j) = \left\{ \begin{aligned} % & 0, & if \ i = 0\ and\ j = 0 \\ & i, & if \ j = 0 \\ & j, & if \ i = 0 \\ & C(i - 1, j - 1), & if\ a[i] = b[j] \\ & min(C(i - 1, j), C(i, j - 1)) + 1, & otherwise \end{aligned} \right. C(i,j)=i,j,C(i1,j1),min(C(i1,j),C(i,j1))+1,if j=0if i=0if a[i]=b[j]otherwise

下面简单列份实现(Lua):

-- get key from two index
function get_key(m, n)return m .. "_" .. n
endfunction edit_dist_iter(a, b, m, n)local edit_dist_buffer = {}edit_dist_buffer[get_key(0, 0)] = 0for i = 1, m doedit_dist_buffer[get_key(i, 0)] = iendfor i = 1, n doedit_dist_buffer[get_key(0, i)] = iendfor i = 1, m dofor j = 1, n dolocal ac = a:sub(i, i)local bc = b:sub(j, j)if ac == bc thenedit_dist_buffer[get_key(i, j)] = edit_dist_buffer[get_key(i - 1, j - 1)]elselocal d1 = edit_dist_buffer[get_key(i - 1, j)]local d2 = edit_dist_buffer[get_key(i, j - 1)]edit_dist_buffer[get_key(i, j)] = math.min(d1, d2) + 1endendendreturn edit_dist_buffer[get_key(m, n)]
endfunction edit_dist(a, b)return edit_dist_iter(a, b, #a, #b)
end

以上的代码使用了迭代形式,我们也可以用递归形式(来编写代码),只是递归会引起不少的重复计算,所以(工程)实现上,我们需要使用缓存来记录计算过的子问题结果(迭代版本也使用了缓存,作用上和递归版本其实也是一致的,记录的也是子问题的结果):

-- get key from two index
function get_key(m, n)return m .. "_" .. n
endfunction edit_dist_recur(a, b, m, n, buffer)if m <= 0 then-- result is trivial, do not need bufferreturn nelseif n <= 0 then-- result is trivial, do not need bufferreturn melselocal ac = a:sub(m, m)local bc = b:sub(n, n)if ac == bc thenlocal d = buffer[get_key(m - 1, n - 1)]if d thenbuffer[get_key(m, n)] = dreturn delselocal d = edit_dist_recur(a, b, m - 1, n - 1, buffer)buffer[get_key(m, n)] = dreturn dendelselocal d1 = buffer[get_key(m - 1, n)]if not d1 thend1 = edit_dist_recur(a, b, m - 1, n, buffer)endlocal d2 = buffer[get_key(m, n - 1)]if not d2 thend2 = edit_dist_recur(a, b, m, n - 1, buffer)endlocal d = math.min(d1, d2) + 1buffer[get_key(m, n)] = dreturn dendend
endfunction edit_dist(a, b)-- create bufferlocal edit_dist_buffer = {}return edit_dist_recur(a, b, #a, #b, edit_dist_buffer)
end

另外还看到一种基于编辑图(Edit Graph)的实现方式,不过思路上仍然和之前的讲述是一致的,实现上则会更复杂些,在此就不列代码了~

更多资料
  • 编辑距离 (Edit distance)
  • 编辑距离算法(Edit Distance)
  • wiki

这篇关于Sweet Snippet 之 字符串编辑距离的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/898246

相关文章

MySQL常用字符串函数示例和场景介绍

《MySQL常用字符串函数示例和场景介绍》MySQL提供了丰富的字符串函数帮助我们高效地对字符串进行处理、转换和分析,本文我将全面且深入地介绍MySQL常用的字符串函数,并结合具体示例和场景,帮你熟练... 目录一、字符串函数概述1.1 字符串函数的作用1.2 字符串函数分类二、字符串长度与统计函数2.1

C# $字符串插值的使用

《C#$字符串插值的使用》本文介绍了C#中的字符串插值功能,详细介绍了使用$符号的实现方式,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录$ 字符使用方式创建内插字符串包含不同的数据类型控制内插表达式的格式控制内插表达式的对齐方式内插表达式中使用转义序列内插表达式中使用

详解MySQL中JSON数据类型用法及与传统JSON字符串对比

《详解MySQL中JSON数据类型用法及与传统JSON字符串对比》MySQL从5.7版本开始引入了JSON数据类型,专门用于存储JSON格式的数据,本文将为大家简单介绍一下MySQL中JSON数据类型... 目录前言基本用法jsON数据类型 vs 传统JSON字符串1. 存储方式2. 查询方式对比3. 索引

MySQL字符串常用函数详解

《MySQL字符串常用函数详解》本文给大家介绍MySQL字符串常用函数,本文结合实例代码给大家介绍的非常详细,对大家学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录mysql字符串常用函数一、获取二、大小写转换三、拼接四、截取五、比较、反转、替换六、去空白、填充MySQL字符串常用函数一、

Python中反转字符串的常见方法小结

《Python中反转字符串的常见方法小结》在Python中,字符串对象没有内置的反转方法,然而,在实际开发中,我们经常会遇到需要反转字符串的场景,比如处理回文字符串、文本加密等,因此,掌握如何在Pyt... 目录python中反转字符串的方法技术背景实现步骤1. 使用切片2. 使用 reversed() 函

MySQL查询JSON数组字段包含特定字符串的方法

《MySQL查询JSON数组字段包含特定字符串的方法》在MySQL数据库中,当某个字段存储的是JSON数组,需要查询数组中包含特定字符串的记录时传统的LIKE语句无法直接使用,下面小编就为大家介绍两种... 目录问题背景解决方案对比1. 精确匹配方案(推荐)2. 模糊匹配方案参数化查询示例使用场景建议性能优

MySQL 获取字符串长度及注意事项

《MySQL获取字符串长度及注意事项》本文通过实例代码给大家介绍MySQL获取字符串长度及注意事项,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录mysql 获取字符串长度详解 核心长度函数对比⚠️ 六大关键注意事项1. 字符编码决定字节长度2

Springboot3+将ID转为JSON字符串的详细配置方案

《Springboot3+将ID转为JSON字符串的详细配置方案》:本文主要介绍纯后端实现Long/BigIntegerID转为JSON字符串的详细配置方案,s基于SpringBoot3+和Spr... 目录1. 添加依赖2. 全局 Jackson 配置3. 精准控制(可选)4. OpenAPI (Spri

使用Python实现base64字符串与图片互转的详细步骤

《使用Python实现base64字符串与图片互转的详细步骤》要将一个Base64编码的字符串转换为图片文件并保存下来,可以使用Python的base64模块来实现,这一过程包括解码Base64字符串... 目录1. 图片编码为 Base64 字符串2. Base64 字符串解码为图片文件3. 示例使用注意

golang float和科学计数法转字符串的实现方式

《golangfloat和科学计数法转字符串的实现方式》:本文主要介绍golangfloat和科学计数法转字符串的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望... 目录golang float和科学计数法转字符串需要对float转字符串做处理总结golang float