【动态规划】求解编辑距离问题

目录

  • 问题描述
  • 递推关系
  • 运行实例
  • 时空复杂度优化
  • Hirschberg 算法

问题描述

编辑距离问题是求解将⼀个字符串转换为另⼀个字符串所需的插⼊、删除、替换的最小次数。 C O M M O M → s u b C O M M U M → s u b C O M M U N → i n s C O M M U N E \mathbb{COMMOM} \overset{sub}{\rightarrow} \mathbb{COMMUM} \overset{sub}{\rightarrow}\mathbb{COMMUN} \overset{ins}{\rightarrow} \mathbb{COMMUNE} COMMOMsubCOMMUMsubCOMMUNinsCOMMUNE上述将单词 COMMOM 变为 COMMUNE 共需要经过至少3次操作。

对编辑距离进行可视化,可以得到序列比对

COMMOM-
COMMUNE
  • 第一行的空格表示插入
  • 第二行的空格表示删除
  • 具有不同字符的列表示替换

编辑距离 = 序列比对中具有不同字符的列数

最小编辑距离 = 最优序列比对中具有不同字符的列数

编辑距离问题也可以这么表述:
对于给定字符串 A [ 1... m ] A[1...m] A[1...m] B [ 1... n ] B[1...n] B[1...n] 求解他们的最小编辑距离 D ( m , n ) D(m,n) D(m,n)


递推关系

假设对 ∀ i < m , ∀ j < n \forall i<m,\forall j<n i<m,j<n,可以计算 A [ 1... i ] A[1...i] A[1...i] B [ 1... j ] B[1...j] B[1...j]的最小编辑距离 D ( i , j ) D(i,j) D(i,j)

COMMOM-
COMMUNE

考虑 A [ 1... m ] A[1...m] A[1...m] B [ 1... n ] B[1...n] B[1...n] 的最优比对,可以发现如下规律:

  1. 最后⼀列不可能是两个空格
  2. 某个串为空串时,最小编辑距离是另⼀个串的长度
  3. A [ m ] A[m] A[m] B [ n ] B[n] B[n] 都存在: D ( m , n ) = D ( m − 1 , n − 1 ) + ( A [ m ] = B [ n ] ? 0 : 1 ) D(m,n) =D(m − 1,n − 1) + (A[m] = B[n]?0 : 1) D(m,n)=D(m1,n1)+(A[m]=B[n]?0:1)
  4. A [ m ] A[m] A[m] B [ n ] B[n] B[n] 有一方为空,删除不为空的那一个: D ( m , n ) = { D ( m − 1 , n ) + 1 A [ m ] a n d − D ( m , n − 1 ) + 1 B [ n ] a n d − D(m,n) = \begin{cases} D(m − 1,n) + 1 & A[m]\quad and \quad- \\ D(m, n − 1) + 1 & B[n]\quad and \quad- \\ \end{cases} D(m,n)={D(m1,n)+1D(m,n1)+1A[m]andB[n]and
  5. 综上,只需要沿着三条路径递归得到最小的那条 D ( m , n ) = { i i f j = 0 j i f i = 0 min ⁡ { D ( m − 1 , n ) + 1 D ( m , n − 1 ) + 1 D ( m − 1 , n − 1 ) + ( A [ m ] = B [ n ] ? 0 : 1 ) o t h e r w i s e D(m,n) = \begin{cases} i &if\quad j=0\\ j &if\quad i=0 \\ \min \begin{cases} D(m − 1,n) + 1 \\ D(m, n − 1) + 1 \\ D(m − 1,n − 1) + (A[m] = B[n]?0 : 1) \end{cases} &otherwise \end{cases} D(m,n)= ijmin D(m1,n)+1D(m,n1)+1D(m1,n1)+(A[m]=B[n]?0:1)ifj=0ifi=0otherwise
  6. 时间复杂度: O ( m n ) O(mn) O(mn) ; 空间复杂度: O ( m n ) O(mn) O(mn)

运行实例

在这里插入图片描述
对于每个 D [ i , j ] D[i,j] D[i,j], 都可以通过 D [ i − 1 , j − 1 ] D[i-1,j-1] D[i1,j1]; D [ i − 1 , j ] D[i-1,j] D[i1,j]; D [ i , j − 1 ] D[i,j-1] D[i,j1]这三个点得到而这三个点又分别对应 替换;删除;插入三种操作。

通过上述递推关系,我们可以自上而下,自左向右构造记录表。在填完记录表后右下角的那个值即为最小编辑距离。接着就是使用回溯的方式,构造满足最小编辑距离的最优比对(如下图右侧所示)
在这里插入图片描述

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>

using namespace std;

// 计算最小编辑距离,并返回最小编辑距离的值,计算编辑距离表dp
int minEditDistance(const string& word1, const string& word2, vector<vector<int>>& dp) {
    int m = word1.length();
    int n = word2.length();

    for (int i = 0; i <= m; ++i) {
        for (int j = 0; j <= n; ++j) {
            if (i == 0) {
                dp[i][j] = j;
            }
            else if (j == 0) {
                dp[i][j] = i;
            }
            else if (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];
}

// 通过回溯法找到所有满足最小编辑距离的操作序列。
void findAllSequences(const string& word1, const string& word2, int i, int j, const string& sequence, vector<string>& sequences, vector<vector<int>>& dp) {
    if (i == 0 && j == 0) {
        sequences.push_back(sequence);
        return;
    }

    if (i > 0 && j > 0 && word1[i - 1] == word2[j - 1]) {
        findAllSequences(word1, word2, i - 1, j - 1, "No operation: " + string(1, word1[i - 1]) + " -> " + string(1, word2[j - 1]) + "\n" + sequence, sequences, dp);
    }

    if (i > 0 && j > 0 && dp[i][j] == dp[i - 1][j - 1] + 1) {
        findAllSequences(word1, word2, i - 1, j - 1, "Replace: " + string(1, word1[i - 1]) + " -> " + string(1, word2[j - 1]) + "\n" + sequence, sequences, dp);
    }

    if (i > 0 && dp[i][j] == dp[i - 1][j] + 1) {
        findAllSequences(word1, word2, i - 1, j, "Delete: " + string(1, word1[i - 1]) + " \n" + sequence, sequences, dp);
    }

    if (j > 0 && dp[i][j] == dp[i][j - 1] + 1) {
        findAllSequences(word1, word2, i, j - 1, "Insert: " + string(1, word2[j - 1]) + " \n" + sequence, sequences, dp);
    }
}

int main() {
    string word1 = "ALTRUISTIC";
    string word2 = "ALGORITHM";

    vector<vector<int>> dp(word1.length() + 1, vector<int>(word2.length() + 1, 0));

    int minDistance = minEditDistance(word1, word2, dp);

    cout << "Minimum Edit Distance between " << word1 << " and " << word2 << " is: " << minDistance << endl;

    vector<string> sequences;
    findAllSequences(word1, word2, word1.length(), word2.length(), "", sequences, dp);

    cout << "Operations to convert " << word1 << " to " << word2 << " are: " << endl;
    for (const string& seq : sequences) {
        cout << seq << "----------"<< endl;
    }

    return 0;
}

运行结果:

在这里插入图片描述


时空复杂度优化

现在我们已经可以计算最小编辑距离,同时构造出最优比对。他们的时空复杂度总结如下:

计算最小编辑距离构造最优比对
时间 O ( m n ) O(mn) O(mn) O ( m + n ) O(m+n) O(m+n)
空间 O ( m n ) O(mn) O(mn) O ( m n ) O(mn) O(mn)

从实际情况来看, O ( m n ) O(mn) O(mn) 的空间比 O ( m n ) O(mn) O(mn) 的时间更难满足,比如当 m = n = 1 0 5 m = n = 10^5 m=n=105

  • 时间上:执行 1 0 10 10^{10} 1010次指令大约需要10秒(假设CPU每秒执行 1 0 9 10^9 109条指令)
  • 空间上:需要 1 0 10 10^{10} 1010bits,大约 40 GB

那么能否使用 O ( m + n ) O(m+n) O(m+n) 的空间来构造最优比对呢?

答:可以使用 Hirschberg 算法。


Hirschberg 算法

Hirschberg 算法是一种高效的线性空间动态规划算法。它通过使用分治策略来降低空间复杂度,从而在线性空间内计算最优比对。

该算法的思想基于以下洞察力:

  • 在动态规划算法中,通常使用二维矩阵来存储中间状态,这导致了 O ( m n ) O(mn) O(mn) 的空间复杂度。
  • 但实际上,可以通过观察计算过程中的对称性,将动态规划的空间复杂度降低到 O ( m + n ) O(m+n) O(m+n)

在这里插入图片描述
在计算动态规划的过程中,我们观察到 D ( i , j ) D(i,j) D(i,j) 的计算仅依赖于 D ( i − 1 , j ) D(i-1,j) D(i1,j) D ( i , j − 1 ) D(i,j-1) D(i,j1) D ( i − 1 , j − 1 ) D(i-1,j-1) D(i1,j1)。基于此,我们可以利用两个长度为 n 的一维数组来存储中间状态,每次只需要保留上一行和当前行的信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/161667.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

macbook ntfs能读不能复制 c盘ntfs拒绝访问怎么解决

如果你是一位Mac用户&#xff0c;你可能会遇到这样的问题&#xff1a;你的Mac能够读取NTFS格式的移动硬盘或U盘&#xff0c;但是不能往里面复制或者修改文件。或者&#xff0c;你的Windows电脑出现了C盘NTFS拒绝访问的错误&#xff0c;导致你无法正常使用系统。这些问题都是由于…

【vue2绘制echarts环状图】vue2使用echarts绘制环状图

效果图&#xff1a; 鼠标悬浮的效果图&#xff1a; 1&#xff1a;安装echarts yarn add echarts5.3.2 或 npm install echarts5.3.2 --save2.局部引入使用 在vue页面引入 <template><div><divref"myChart"style"{width: 400px;height: 350…

VMware Workstation Pro 12 ubuntu 20.04 突然奔溃,重新打开后导致win11系统蓝屏问题

1、虚拟机在执行一个程序时候&#xff0c;突然导致系统win11蓝屏 2、重新打开提示磁盘打开异常&#xff0c;网络搜索发现要删除磁盘lock文件&#xff0c;删除后&#xff0c;重启过程中还是会报各种异常 后来把所有的临时文件都删除了&#xff0c;就可以了 临时文件&#xff1…

如何去开发一个springboot starter

如何去开发一个springboot starter 我们在平时用 Java 开发的时候&#xff0c;在 pom.xml 文件中引入一个依赖就可以很方便的使用了&#xff0c;但是你们知道这是如何实现的吗。 现在我们就来解决这一个问题&#xff01; 创建 SpringBoot 项目 首先我们要做的就是把你想要给别…

wpf devexpress 开始点

此教程示范如何创建registration form和DevExpress WPF Data Editors 开始点 此项目源码 这个解决方案包含几个项目-每一个项目对应一个教程 RegistrationForm.BaseProject项目是基于工作的解决方案。项目包含三个视图&#xff1a;MainView&#xff0c;RegistraionView&…

Os-ByteSec

Os-ByteSec 一、主机发现和端口扫描 主机发现&#xff0c;靶机地址192.168.80.144 端口扫描&#xff0c;开放了80、139、445、2525端口 二、信息收集 访问80端口 路径扫描 dirsearch -u "http://192.168.80.144/" -e *访问扫描出来的路径&#xff0c;没有发现…

IO流-序列化流

一&#xff0c;序列化&#xff08;把java对象写到对象中去&#xff09; 二&#xff0c; Object OutputStream(对象字节输出流) 三&#xff0c;案例 package BigDecimal;import java.io.FileOutputStream; import java.io.ObjectOutputStream;public class Main {public static…

​软考-高级-系统架构设计师教程(清华第2版)【第14章 云原生架构设计理论与实践(P496~526)-思维导图】​

软考-高级-系统架构设计师教程&#xff08;清华第2版&#xff09;【第14章 云原生架构设计理论与实践&#xff08;P496~526&#xff09;-思维导图】 课本里章节里所有蓝色字体的思维导图

​软考-高级-系统架构设计师教程(清华第2版)【第13章 层次式架构设计理论与实践(P466~495)-思维导图】​

软考-高级-系统架构设计师教程&#xff08;清华第2版&#xff09;【第13章 层次式架构设计理论与实践&#xff08;P466~495&#xff09;-思维导图】 课本里章节里所有蓝色字体的思维导图

数据库的分库分表 详解

前言 一个系统随着用户量上升&#xff0c;产生的数据也越来越多&#xff0c;到达一定程度&#xff0c;数据库就会产生瓶颈。 首先单机数据库所能承载的连接数&#xff0c;io和吞吐量都是有限的&#xff0c;并发量上来数据库就渐渐顶不住了。 如果单表的数据量过大&#xff0…

阿里巴巴java开发手册-编程规约

编程规约 命名风格常量定义代码格式OOP 规约日期时间集合处理并发处理控制语句注释规约前后端规约其他 命名风格 【强制】代码中的命名均不能以下划线或美元符号开始&#xff0c;也不能以下划线或美元符号结束。 反例&#xff1a;_name / name / n a m e / n a m e / n a m e…

腾讯云服务器租用价格,腾讯云服务器价格流量怎么算?

首先&#xff0c;让我们来看看腾讯云服务器租用价格。根据您的需求不同&#xff0c;腾讯云提供了多种不同的配置选项&#xff0c;从轻量级应用服务器到高性能的GPU服务器&#xff0c;都可以满足您的需求。以下是一些常见的腾讯云服务器租用价格&#xff1a; 一、腾讯云服务器租…

vs2017 编译Qt 5.11.2 源码

SDK 10.0.22000.194 有 2种编译方式 &#xff0c;第二种 看下面 方式一: 1、问题描述&#xff1a; 使用VS编译程序时&#xff0c;运行库选择多线程&#xff08;/MT&#xff09;&#xff0c;表示采用多线程静态release的方式进行编译。 但是&#xff0c;发现编译是不能通过的…

使用 Filebeat+Easysearch+Console 打造日志管理平台

近年来&#xff0c;日志管理平台越来越流行。使用日志管理平台可以实时地、统一地、方便地管理和查看日志&#xff0c;挖掘日志数据价值&#xff0c;驱动运维、运营&#xff0c;提升服务管理效率。 方案架构 Beats 是轻量级采集器&#xff0c;包括 Filebeat、Metricbeat 等。E…

记一次服务器配置文件获取OSS

一、漏洞原因 由于网站登录口未做双因子校验,导致可以通过暴力破解获取管理员账号,成功进入系统;未对上传的格式和内容进行校验,可以任意文件上传获取服务器权限;由于服务器上配置信息,可以进一步获取数据库权限和OSS管理权限。二、漏洞成果 弱口令获取网站的管理员权限通…

资产设备管理系统

dtAsset 是一个固定资产设备管理系统&#xff0c;它专为中小企业的需求而设计。该软件提供了对常用资产设备进行信息化管理的功能&#xff0c;并支持自定义设备类型、导入导出数据、维护工作统计、采购管理、文档管理、运维监控 (使用 Zabbix)、知识库等功能。 主要模块 1.系统…

ogrinfo不是内部或者外部命令

这个是GDAL的问题&#xff0c;我是通过OSGeo4w安装的&#xff0c;出来就是这个问题&#xff0c;教程没有仔细看干。 第一次安装&#xff0c;选择express install&#xff01;&#xff01;&#xff01;&#xff01; 第一次安装&#xff0c;选择express install&#xff01;&…

动手学深度学习——循环神经网络的简洁实现(代码详解)

文章目录 循环神经网络的简洁实现1. 定义模型2. 训练与预测 循环神经网络的简洁实现 # 使用深度学习框架的高级API提供的函数更有效地实现相同的语言模型 import torch from torch import nn from torch.nn import functional as F from d2l import torch as d2lbatch_size, …

黑马程序员 学成在线项目 第1章 项目介绍环境搭建v3.1

第1章 项目介绍&环境搭建v3.1 1.项目背景 1.1 在线教育市场环境 以下内容摘自艾瑞&#xff1a;2020年在线教育行业洞察&#xff1a;To B赛道篇_网络服务_艾瑞网 在线教育行业是一个有着极强的广度和深度的行业&#xff0c;从校内到校外&#xff1b;从早幼教到职业培训&…