算法系列(四) 字符串的相似度

我们把两个字符串的相似度定义为:将一个字符串转换成另外一个字符串的代价(转换的方法可 能不唯一),转换的代价越高则说明两个字符串的相似度越低。比如两个字符串:“SNOWY”和 “SUNNY”,下面给出两种将“SNOWY”转换成“SUNNY”的方法:

变换1:

   S - N O W Y

   S U N N - Y

  Cost = 3 (插入U、替换O、 删除W)

变换2:

   - S N O W - Y

   S U N - - N Y

   Cost = 5 (插入S、替换S、删除O、删除W、插入N)

分析问题

我们可以把这种相似度理解为:把一个字符串(source)通过“插入、删除和替换”这样的编辑操 作变成另外一个字符串(target)所需要的最少编辑次数,也就是两个字符串之间的编辑距离(edit distance)。能否给出一个算法,求解任意两个字符串之间的编辑距离?

从题目给出的例子可 知,将一个字符串经由插入、删除或替换等操作转换成另外一个字符串的方法不止一种,所需要做的 编辑次数也不相同,如果有某种方法能够用最小的修改次数完成转换,这种方法的编辑次数就是我们 要求的编辑距离。很显然,这是个求最优解的问题。

提到最优解问题,首先可以考虑使用贪婪 法,但是本题显然是一个多阶段决策类型的最优解问题,对source字符串做最小的修改变换到target 字符串,需要在处理过程中的每个阶段都选择修改最小的方式,但是本题中每个阶段之间都不是孤立 的,受到前面已经确定的决策和后面可选的决策共同影响,无法通过对每一次决策的最优决策简单堆 叠出最后的最优结果,因此,排除贪婪法。

动态规划法(Dynamic Programming)

对于多阶段决策类型的问题,应该优先考虑动态规划法(Dynamic Programming, DP)。动态规划 法是解决多阶段决策最优化问题常用的一种思想方法[1],也是所有解题方法中最抽象的一种方法。使 用动态规划法解决问题的关键有两点,一点是定义子问题的最优子结构【注解1】,另一点是确定子问 题最优解的堆叠方式。定义最优子结构就是分解子问题,可以用递推的方式,也可以用递归的方式, 基本原则就是将问题分成M个子问题,同时确定每个子问题的最优解与其它N(N小于M)个子问题之间 的关系。子问题最优解的堆叠方式是指最优决策序列和它的子序列的递推关系,包括子问题最优解的 递推关系和边界值两部分。对于一个问题,如果能够找最优子结构的定义方式(包括子问题之间的关 系)和子问题最优解的堆叠方式,并且每个子问题最优解都满足无后效性【注解2】,则该问题就可以 尝试用动态规划法解决这个问题。

以本题为例,假设source字符串有n个字符,target字符串 有m个字符,如果将问题定义为求解将source的1-n个字符转换为target的1-m个字符所需要的最少编 辑次数(最小编辑距离),则其子问题就可以定义为将source的1-i个字符转换为target的1-j个字 符所需要的最少编辑次数,这就是本问题的最优子结构。我们用d[i, j]表示source[1..i]到target [1..j]之间的最小编辑距离,则计算d[i, j]的递推关系可以这样计算出来:

如果source[i] 等于target[j],则:

d[i, j] = d[i, j] + 0                                               (递推式 1)

如果source[i] 不等于target [j],则根据插入、删除和替换三个策略,分别计算出使用三种策略得到的编辑距离,然后取最小的一 个:

d[i, j] = min(d[i, j - 1] + 1,d[i - 1, j] + 1,d[i - 1, j - 1] + 1 )            (递推式 2)

d[i, j - 1] + 1 表示对source[i]执行 插入操作后计算最小编辑距离

d[i - 1, j] + 1 表示对source[i]执行删除操作后计算最小编 辑距离

d[i - 1, j - 1] + 1表示对source[i]替换成target[i]操作后计算最小编辑距离

d[i, j]的边界值就是当target为空字符串(m = 0)或source为空字符串(n = 0)时所计算 出的编辑距离:

m = 0,对于所有 i:d[i, 0] = i

n = 0,对于所有 j:d[0, j] = j

时间: 2024-11-02 12:08:37

算法系列(四) 字符串的相似度的相关文章

[算法系列之十四]字符串匹配之Morris-Pratt字符串搜索算法

前言 我们前面已经看到,蛮力字符串匹配算法和Rabin-Karp字符串匹配算法均非有效算法.不过,为了改进某种算法,首先需要详细理解其基本原理.我们已经知道,暴力字符串匹配的速度缓慢,并已尝试使用Rabin-Karp中的一个散列函数对其进行改进.问题是,Rabin-Karp的复杂度与强力字符串匹配相同,均为O(mn). 我们显然需要采用一种不同方法,但为了提出这种不同方法,先来看看暴力字符串匹配有什么不妥之处.事实上,再深入地研究一下它的基本原理,就能找到问题的答案了. 在暴力匹配算法中,需要检

[算法系列之二十四]后缀树(Suffix Tree)

之前有篇文章([算法系列之二十]字典树(Trie))我们详细的介绍了字典树.有了这些基础我们就能更好的理解后缀树了. 一 引言 模式匹配问题 给定一个文本text[0-n-1], 和一个模式串 pattern[0-m-1],写一个函数 search(char pattern[], char text[]), 打印出pattern在text中出现的所有位置(n > m). 这个问题已经有两个经典的算法:KMP算法 ,有限自动机,前者是对模式串pattern做预处理,后者是对待查证文本text做预处

算法系列(十四) 狼、羊、菜和农夫过河问题

题目描述:农夫需要把狼.羊.菜和自己运到河对岸去,只有农夫能够划船,而且船比较小,除农 夫之外每次只能运一种东西,还有一个棘手问题,就是如果没有农夫看着,羊会偷吃菜,狼会吃羊. 请考虑一种方法,让农夫能够安全地安排这些东西和他自己过河. 这个题目考察人的快速逻辑运算和短期记忆力.分析一下,在狼->羊->菜这个食物链条中 ,"羊"处在关键位置,解决问题的指导思想就是将"羊"与"狼"和"菜"始终处于隔离状态,也 就是说

[算法系列之二十六]字符串匹配之KMP算法

一 简介 KMP算法是一种改进的字符串匹配算法,由D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,因此人们称它为克努特-莫里斯-普拉特操作(简称KMP算法).KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的. 二 基于部分匹配表的KMP算法 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含搜索串"ABCDABD"? 步骤1:字符串"BBC ABC

算法系列(十九) 用天文方法计算日月合朔(新月)

中国农历的朔望月是农历历法的基础,而朔望月又是严格以日月合朔发生的那一天作为月首,因此日 月合朔时间的计算是制定农历历法的关键.本文将介绍ELP-2000/82月球运行理论,以及如何用ELP- 2000/82月球运行理论计算日月合朔时间. 要计算日月合朔时间, 首先要对日月合朔这一天文现象进行数学定义.朔望月是在地球上观察到的月相周期,平均长度约等于 29.53059日,而恒星月(天文月)是月亮绕地球公转一周的时间,长度约27.32166日.月相周期长度比恒 星月长大约两天,这是因为在月球绕地球

[算法系列之二十]字典树(Trie)

一 概述 又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计. 二 优点 利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希表高. 三 性质 (1)根节点不包含字符,除根节点外每一个节点都只包含一个字符: (2)从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串: (3)每个节点的所有子节点包含的字符都不相同. 单词列表为"apps&

缓存淘汰算法系列之3——FIFO类

缓存淘汰算法系列之3--FIFO类 1 FIFO 1.1. 原理 按照"先进先出(First In,First Out)"的原理淘汰数据. 1.2. 实现 FIFO队列,具体实现如下: 1. 新访问的数据插入FIFO队列尾部,数据在FIFO队列中顺序移动: 2. 淘汰FIFO队列头部的数据: 1.3. 分析 l 命中率 命中率很低,因为命中率太低,实际应用中基本上不会采用. l 复杂度 简单 l 代价 实现代价很小. 2. Second Chance 2.1. 原理 FIFO算法的改进

计算字符串的相似度

在看完<编程之美>一书的"计算字符串的相似度"一文后,对该书最后提出的问题作一点回忆与思考. 这里先将原问题再复述一遍: 原文的问题描述: 许多程序会大量使用字符串.对于不同的字符串,我们希望能够有办法判断其相似程序.我们定义一套操作方法来把两个不相同的字符串变得相同,具体的操作方法为: 1.修改一个字符(如把"a"替换为"b"); 2.增加一个字符(如把"abdd"变为"aebdd"); 3.

算法系列(二十) 计算中国农历(二)

所谓的"天文算法",就是利用经典力学定律推导行星运转轨道,对任意时刻的行星位置进行精确计 算,从而获得某种天文现象发生时的时间,比如日月合朔这一天文现象就是太阳和月亮的地心黄经(视黄 经)差为0的那一瞬间.能够计算任意时刻行星位置的一套理论就被称为星历表,比较著名的星历表有美 国国家航空航天局下属的喷气推进实验室发布的DE系列星历表,还有瑞士天文台在DE406基础上拓展的瑞 士星历表等等.根据行星运行轨道直接计算行星位置通常不是很方便,更何况大多数民用天文计算用不上 那么多精确的轨道参