动态规划经典例子——编辑距离问题

问题描述:

  两个字符串,一个是起点字符串,另一个是终点。

  例如,起点字符串ddl到终点字符串de的转换步骤如下:

  ddl->del->def。

  编辑距离为2。

算法分析:

  首先考虑上面例子中ddl的第一个字符和def的第一个字符,它们是一样的,所以只需要计算a[2...lengthA]和b[2...lengthB](dl和ef)之间的距离即可。

  若两个字符串的第一个字符不同,例如adl和def,可以三选一:

  • 把终点串的第一个字符插入到起点串的第一个字符之前(adl->dadl),然后计算a[1...lengthA]和b[2...lengthB](dadl和def)的距离即可;
  • 删除起点串的第一个字符(adl->dl),然后计算a[2...lengthA]和b[1...lengthB](dl->def)的距离即可;
  • 修改起点串的第一个字符成终点串的第一个字符(adl->ddl),然后计算a[2...lengthA]和b[2...lengthB](dl和ef)的距离即可。

  考虑起点串的第i个字符和终点串的第j个字符的话也是一样的。

当不考虑起点串的前i-1字符和终点串的前j-1个字符,如果起点串的第i个字符和终点串的第j个字符相等,即a[i-1] = b[j-1],则只需要计算a[i...lengthA]和b[j...lengthB]之间的距离即可。

  如果不相等,可以三选一:

  • 把终点串的第j个字符插入到起点串的第i个字符之前,然后计算a[i...lengthA]和b[j+1...lengthB]的距离即可;
  • 删除起点串的第i个字符,然后计算a[i+1...lengthA]和b[j...lengthB]的距离即可;
  • 修改起点串的第i个字符成终点串的第j个字符,之然后计算a[i+1...lengthA]和b[j+1...lengthB]的距离即可;

   那么进行三选一的依据是什么呢?是起点串的前i-1字符和终点串的前j-1个字符的编辑距离。

  递归方程:

  edit[i-1][j]+1相当于给起点串的最后插入了终点串的最后的字符,插入操作使得edit+1,之后计算edit[i-1][j];

  edit[i][j-1]+1相当于将起点串的最后字符删除,删除操作edit+1,之后计算edit[i][j-1];

  edit[i-1][j-1]+flag相当于通过将起点串的最后一个字符替换为终点串的最后一个字符。若a[i-1] = b[j-1],flag = 0;若a[i-1] != b[j-1],flag = 1。

  

#include<iostream>
#include<string.h>
using namespace std;

int main() {
    char a[2000], b[2000];

    cin.getline((a+1), 2001);
    cin.getline((b+1), 2001);

    int lengthA = strlen(a) - 1;
    int lengthB = strlen(b) - 1 ;

    int editDistance[2001][2001];
    editDistance[0][0] = 0;

    for(int i = 1; i <= lengthA; i++) {
        editDistance[i][0] = i;
    }
    for(int i = 1; i <= lengthB; i++) {
        editDistance[0][i] = i;
    }
    for(int i = 1; i <= lengthA; i++)
        for(int j = 1; j <= lengthB; j++) {
            if(a[i] == b[j]) {
                editDistance[i][j] = editDistance[i-1][j-1];
            }
            else {
                editDistance[i][j] = min(editDistance[i-1][j], min(editDistance[i][j-1], editDistance[i-1][j-1])) + 1;
            }
        }

    cout << editDistance[lengthA][lengthB];

    return 0;
}

复杂度分析

  时间复杂度:O(m*n)

  空间复杂度:O(1)

心得

递归方程很重要。

原文地址:https://www.cnblogs.com/Texas/p/11717255.html

时间: 2024-11-10 13:29:45

动态规划经典例子——编辑距离问题的相关文章

nyist oj 311 全然背包 (动态规划经典题)

全然背包 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描写叙述 直接说题意,全然背包定义有N种物品和一个容量为V的背包.每种物品都有无限件可用.第i种物品的体积是c,价值是w. 求解将哪些物品装入背包可使这些物品的体积总和不超过背包容量,且价值总和最大.本题要求是背包恰好装满背包时,求出最大价值总和是多少. 假设不能恰好装满背包,输出NO 输入 第一行: N 表示有多少组測试数据(N<7). 接下来每组測试数据的第一行有两个整数M.V. M表示物品种类的数目,V表示背

动态规划经典题目:最大连续子序列和

最大连续子序列和问题 给定k个整数的序列{N1,N2,...,Nk },其任意连续子序列可表示为{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j <= k.最大连续子序列是所有连续子序中元素和最大的一个,例如给定序列{ -2, 11, -4, 13, -5, -2 },其最大连续子序列为{11,-4,13},最大连续子序列和即为20. 注:为方便起见,如果所有整数均为负数,则最大子序列和为0. 解决这样一个问题是一个很有趣的过程,我们可以尝试着从复杂度比较高的算法

递归的几个经典例子

注意:构造方法不可递归,否则是无限创建对象; 递归的几个经典例子: 1.HannoiTower 1 import java.util.Scanner; 2 public class HanoiTower{ 3 //level代表盘子个数;三个char类型代表柱子 4 public static void moveDish(int level, char from, char inter, char to){ 5 if(level == 1){ 6 System.out.println("从&qu

小猪的数据结构辅助教程——2.5 经典例子:约瑟夫问题的解决

小猪的数据结构辅助教程--2.5 经典例子:约瑟夫问题的解决 标签(空格分隔): 数据结构 约瑟夫问题的解析 关于问题的故事背景就不提了,我们直接说这个问题的内容吧: 一堆人,围成一个圈,然后规定一个数N,然后依次报数,当报数到N,这个人自杀,其他人鼓掌!啪啪啪, 接着又从1开始报数,报到N又自杀-以此类推,直到死剩最后一个人,那么游戏结束! 这就是问题,而我们用计算机模拟的话,用户输入:N(参与人数),M(第几个人死),结果返回最后一个人! 类似的问题有跳海问题,猴子选王等,下面我们就以N =

信号量基础和两个经典例子

信号量基础和两个经典例子 信号量(semaphore) 用于进程中传递信号的一个整数值. 三个操作: 1.一个信号量可以初始化为非负值 2.semWait操作可以使信号量减1,若信号量的值为负,则执行semWait的进程被阻塞.否则进程继续执行. 3.semSignal操作使信号量加1.若信号量的值小于等于0,则被semWait操作阻塞的进程讲被接触阻塞. ps: semWait对应P原语,semSignal对应V原语. 信号量以及PV原语的C语言定义如下 struct semaphore {

python经典例子

http://wangwei007.blog.51cto.com/68019/1106735  检查Linux系统日志error和mysql错误日志的脚本 http://wangwei007.blog.51cto.com/68019/1102836  pickle http://wangwei007.blog.51cto.com/68019/1045577  python用zipfile模块打包文件或是目录.解压zip文件实例 http://blog.163.com/kefan_1987/blo

storm经典例子的wordcount的实现

storm有个经典的例子wordcount,其实这几乎可以说是大数据的经典例子了,mapreduce也会有这个例子.但是storm给的例子包里的WordCountTopology用到了python的调用,直接用eclipse跑起来的话会报错,这里做了个小改动. 1.WordCountTopology.java package storm.starter; import backtype.storm.Config; import backtype.storm.LocalCluster; impor

nyist oj 37 回文字符串 (动态规划经典)

回文字符串 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描述 所谓回文字符串,就是一个字符串,从左到右读和从右到左读是完全一样的,比如"aba".当然,我们给你的问题不会再简单到判断一个字符串是不是回文字符串.现在要求你,给你一个字符串,可在任意位置添加字符,最少再添加几个字符,可以使这个字符串成为回文字符串. 输入 第一行给出整数N(0<N<100) 接下来的N行,每行一个字符串,每个字符串长度不超过1000. 输出 每行输出所需添加的最少字符

nyist oj 214 单调递增子序列(二) (动态规划经典)

单调递增子序列(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 给定一整型数列{a1,a2...,an}(0<n<=100000),找出单调递增最长子序列,并求出其长度. 如:1 9 10 5 11 2 13的最长单调递增子序列是1 9 10 11 13,长度为5. 输入 有多组测试数据(<=7) 每组测试数据的第一行是一个整数n表示序列中共有n个整数,随后的下一行里有n个整数,表示数列中的所有元素.每个整形数中间用空格间隔开(0<n<=1