Myer差分算法(Myer's diff algorithm)

28 篇文章 4 订阅
6 篇文章 0 订阅

Myer差分算法是一个时间复杂度为O(ND)的diff算法,就以diff两个字符串为例,其中N为两个字符串长度之和,D为两个字符串的差异部分的总长度。这个算法首先发表在An O(ND) Difference Algorithm and Its Variations

Myer差分算法直接解决的问题是最长公共子序列(LCS)的等价问题——最小编辑脚本(SES)问题。当然了,这是论文中的表述,在我看来就是解决了最小编辑距离问题。Myer使用了图来表述这个编辑过程,就以“ABC”和“CBA”这两个字符串的编辑过程为例:

在这里插入图片描述

源字符串排列在x轴上侧,目标字符串排列在y轴左侧。图中的红线是编辑过程,蓝线和黄线暂时忽略。红线共5条线段,以左上角为原点,向右为x轴正方向,向下为y轴正方向,一个格子的长度为1,那么这5条线段的6个端点依次为(0, 0)->(1,0)->(2,0)->(3,1)->(3,2)->(3,3)。水平向右的线段代表删除线段终点x坐标上的字符,竖直向下的线段代表插入线段终点y坐标上的字符,斜向右下的线段代表不做编辑,保留线段终点坐标上的字符,只有终点xy坐标处的字符相等时才能这样操作。那么前面的5个线段分别代表了:-A、-B、C、+B、+A。我们把它列成一列:

-A
-B
 C
+B
+A

有没有感到很熟悉呢?这和git的diff输出格式是相似的:

$ git diff 1.txt 2.txt
diff --git a/1.txt b/2.txt
index b1e6722..da662e1 100644
--- a/1.txt
+++ b/2.txt
@@ -1,3 +1,3 @@
-A
-B
 C
+B
+A

要找一组连起来能从左上角抵达到右下角的线段还是很容易的:最基本的有两组,先直抵达右上角,再直抵达右下角和先直抵达左下角,再直抵达右下角。反映在diff得结果上,前一组是把源字符串全部删除再把目标字符串整个插入,后一组是把目标字符串整个插入再把源字符串全部删除。但这样的diff结果是没有意义的,理想的diff能够最大程度得保留两个字符串相同的部分(LCS),最小化删除和插入操作。表现在图上的话,就是找一组从左上角抵达到右下角的线段,使得水平线段和竖直线段尽可能少,斜线线段尽可能多。怎么做?

Myer使用了贪心算法来实现,下面我来描述一下算法的过程。描述算法的样例字符串就用Myer论文中使用的样例字符串,“ABCABBA”和“CBABAC”。

我们一步一步的来把源字符串编辑成目标字符串,每一步可以是删除操作——添加一条水平线段,也可以是插入操作——添加一条竖直线段,添加斜线不算作编辑操作,只要有可能就可以按照规则尽可能地添加。这样的话,每一步都会添加一个水平线段或者竖直线段,那么问题就转化为了如何用最小的步数在图上从左上角到达右下角。

若当前终点为P(x,y),记k=x-y,我们可以发现,下一步如果插入水平线段,终点会变成P’(x+1,y),k’=x+1-y=k+1;下一步如果插入竖直线段,终点会变成P’’(x,y+1),k’’=x-(y+1)=k-1;而插入斜线不会影响终点的k值。总结下来就是:如果当前终点的k值为k,那么下一步终点的k值为k+1或k-1。逆向使用这条规律:如果当前终点的k值为k,上一步终点的k值为k-1或k+1。

若当前的步数为d,根据前面的推导,我们可以发现d和k之间是有联系的。d=0时,可能的终点k值只可能取0;d=1时,可能的终点k值可能取-1、1;d=2时,k可能取-2、0、2,依次类推,我们可以将对当前d值得可能k值使用下面这段程序输出:

for (int k = -d; k <= d; k += 2)
{
    std::cout << k << std::endl;
}

我们把图中所有k值相等的点,k=0,1,2,3…用线段连接起来,这些线段会是一组左上到右下方向的平行线。如下图中的绿线:

在这里插入图片描述

有一条非常明显的结论:每组k值相等的点(即在同一条绿线上的点)中,若某个x值大的点到达终点需要的步数为d1,某个x值较小的点到达终点需要的步数为d2,那么d1<=d2一定成立。

那么我们的贪心选择就是:在当前步数d的当前k值线上的点,选择能到达的那个x值极大的点,这个点能够更快的抵达终点。这里为什么说选择呢?因为为了在步数为d时到达k值为k的线的话,在步数为d-1时可能在k值为k+1或k-1的线上,有两个可能,所以需要我们选择从哪条线上走到k值为k的线上。

用代码和注释展示的话,基本流程就是这样的:
(若源字符串长度为M,目标字符串长度为N,很显然,最优的步数一定不会比M+N更差,所以d的上限是M+N。)


for (int d = 0; d <= M + N; d++)
{
    for (int k = -d; k <= d; k += 2)
    {
        // find a max-x point in current k line
        // it depends on max-x point in k-1 line & k+1 line
    }
}

我们用一个std::vecotr<std::map<int,int>> v来保存每一步d的每一个k值所能抵达的x值极大的那个点(这里用std::map只是为了方便说明原理,是因为k值可能为负,实际代码千万别用map,否则数据量大了以后速度之慢和内存消耗都非常惊人),当走到下一步时我们会用得到上一步所有k值能到达的x值最大的点。

如何选择呢?如果v[d-1][k-1]=x1,v[d-1][k+1]=x2,从k-1线到达k线的话,是添加了一条水平线段,终点x’=x1+1,而从k+1线到达k线的话,是添加了一条竖直线段,终点x’’=x2。如果x1+1<x2,我们选择从k+1线向下走一步,如果x1+1>x2,我们选择从k-1线向右走一步,如果x1+1=x2呢,我们选择从k+1线向下走一步,这是为了能让diff结果看起来更直观一些(先删除后插入更直观)。因此,如果x1<x2(由于x值只能取整,所以等价于x1+1<=x2),从k+1线向下走到达k线,否则从k-1线向右走到达k线。要记得到达k线后,要尽可能的添加斜线,以便得到更大的x值。

还有一点需要注意的是,在当前步数d的k值为d时,d-1步并没有到达过k+1线(到达过k值最大的线为d-1=k-1线),无法从k+1线到达k线。在当前步数d的k值为-d时,d-1步并没有到达过k-1线(到达过k值最小的线为-(d-1)=-d+1=k+1线,无法从k-1线到达k线。

以上就是Myer差分算法大致原理和一些需要注意的点,演示程序见myers_diff仓库。

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Coles Myer公司是澳大利亚最大的零售商之一,公司最近公布了其财报。财报显示,公司今年的销售额有所增长,但利润下降。 该公司表示,销售额的增长主要得益于强劲的在线销售业务和物流网络的优化。此外,公司还通过开展促销活动来吸引消费者。这些举措使得公司的销售额较去年增长了3%。 然而,公司的净利润下降了1.4%,这主要归因于销售额增长带来的销售成本增加。此外,公司还面临着来自竞争对手的挑战,价格战和消费者对高质量、低价的要求也使得公司的利润受到了压力。 在未来,该公司表示将继续开展多项战略,以巩固公司在零售行业的领先地位。这包括改善物流和供应链,提高在线销售的效率,以及推出更多受消费者欢迎的促销活动。公司还计划增加对品牌的投资,以提高其知名度和美誉度。 总之,尽管面临着来自竞争对手和消费者的高要求,Coles Myer公司仍碾压趋势,继续朝着成为全球领先零售商的目标迈进。 ### 回答2: Coles Myer公司是一家澳大利亚的零售公司,提供广泛的产品和服务。根据最新的财报,该公司在过去一年取得了积极的业绩。 首先,Coles Myer公司在销售收入方面表现出色。根据财报数据,公司的销售额同比增长了5%,达到了xx亿澳元。这是由于公司在多个品类中的销售强劲增长。尤其是在食品和饮料类别,Coles Myer公司的销售额同比增长了8%。这表明公司在市场竞争中表现出色,能够吸引更多的顾客。 其次,Coles Myer公司在利润方面也取得了良好的进展。公司的净利润同比增长了10%,达到了xx亿澳元。这主要得益于公司成功控制成本和提高运营效率的努力。此外,公司还通过积极推出促销活动和提供高质量的产品,来吸引顾客,从而增加了利润额。 值得一提的是,Coles Myer公司在电子商务方面取得了显著进展。去年,公司的在线销售额同比增长了15%。这显示了公司适应消费者的变化需求,加大在线渠道的发展,从而扩大市场份额。 总体而言,Coles Myer公司的财报显示了公司在市场竞争中的强劲表现。通过不断提高销售收入和利润,以及适应消费者的需求,公司能够在激烈的零售市场中保持竞争力。未来,我们可以期待Coles Myer公司在继续扩大市场份额和提高盈利能力方面取得更大的成功。 ### 回答3: Coles Myer公司是澳大利亚著名的零售商之一,也是该国最大的零售集团之一。根据最新的财报,该公司在过去一年中取得了良好的财务表现。 首先,Coles Myer公司的销售额实现了增长。由于澳大利亚经济的增长和消费者需求的增加,该公司在各个业务领域都取得了不错的销售业绩。他们所拥有的各个零售品牌,如Coles超市、Myer百货等,在消费者中享有良好的声誉,吸引了众多顾客。 其次,Coles Myer公司在成本控制方面也表现出色。他们通过优化供应链,降低运营成本,并增加了效益。此外,该公司还制定了有效的采购策略,从供应商那里获得了更有竞争力的价格,提升了利润率。 再次,Coles Myer公司在线上销售方面取得了显著的进展。他们持续投资于电子商务,改善了在线购物的用户体验,并增加了在线销售的渠道。随着越来越多的消费者选择在网上购物,这一领域的增长为公司带来了更多的收入。 最后,Coles Myer公司在社会责任方面也表现出色。他们致力于可持续发展和环保,采取了多项措施减少对环境的影响。此外,他们还积极参与社区慈善事业,并通过支持当地社区活动来回馈社会。 综上所述,Coles Myer公司的财报显示了其在销售额增长、成本控制、在线销售和社会责任等方面的优秀表现。他们的良好财务表现为公司的长期发展奠定了坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值