题目链接:http://poj.org/problem?id=3356

思路分析:题目为经典的编辑距离问题,其实质为动态规划问题;

编辑距离问题定义:给定一个字符串source,可以对其进行复制,替换,删除,增加操作,另外根据具体情况已经规定了每种操作的cost,现在要求求出一个操作序列,使其变为一个给定的字符串dest,并且该操作序列的cost的和最小(在该题目中复制开销为0,其他开销为1);

该问题为动态规划问题,先对该问题进行分析:

1)发掘最优子结构:

假设源字符串为S[0, 1, 2,..,n-1],其长度为n,目标字符串为D[0, 1, 2, ...., m-1],长度为m,则该问题转换为求一个cost最小的操作序列将

S[0,1,2,...,n-1]转换为D[0, 1, 2, ...., m-1];先考虑如何将S[0]转换为D[0];为了将S[0]转换为D[0],我们先选择一个操作,假设该操作是产生最

优的操作序列的第一个操作,这样我们就能将S[0]转换为D[0],则原来的问题在该操作后产生了一个子问题(在不同的动态规划问题中可能会产

生不同的子问题个数),即求一个cost最小的操作序列将S[1, 2, ... , n-1]转换为D[1, 2, ..., m-1],我们可以证明该子问题的最优解可以构造出原

来问题的最优解,这样我们就发现了该问题的最优子结构;另外,我们还需要考虑第一步的选择有多少种(不同动态规划问题的选择的可能性的

种类数目不同),即将S[0]转换为D[0]可以有多少种操作方法,明显在这个问题中有4种;

2)重叠子问题

如果该问题的递归算法反复地求解子问题,那么我们就称该最优化问题具有重叠子问题性质;在分治算法中,递归算法会生成全新的子问题,

子问题与子问题之间是无关的;而动态规划算法不同,如求斐波那契数列的递归算法中求数列f[n]需要求解f[n-1]与f[n-2],而f[n-1]=f[n-2]+f[n-3],

可以看到,在求斐波那契数列的递归算法中f[n-2]被求解多次,则求具有重叠子问题的结构,但是求斐波那契数列算法不是动态规划算法,因为其

不具有最优子结构,这里提出该问题是让大家对重叠子问题有一个具体的认识;现在,我们可以明显看到,在求解编辑距离问题中,我们做出一次

选择,就会产生一个子问题,因为在每一步中我们可能会做出多个选择,所以会求解多个相同的子问题,如在第一步中,我们可以选择复制(如果

S[0]==D[0]),删除,替换,增加操作,每个选择的操作就会产生相同的子问题,即求解S[1,2, .., m]转换D[1, 2, ..., n]的最小的cost的操作序列;

所以该问题具有重叠子问题;

3)解法:

对于该问题,我们刻画该问题的问题空间:假设dp[i][j]表示从字符串S[i, i+1, i+2, ...., m-1]转换为字符串D[j, j+1, j+2, ...., n-1]的操作序列的最小的cost和,

则原问题为求dp[0][0];

对于特殊的情况:

dp[i, n] = m-i,表示使S[i, i+1, ...,m-1]转换为空字符串,只能删除m-i个字符,所以最小的cost和为m-i;

dp[m, j] = n-j,表示使空字符串转换为D[j, j+1, ..., n-1],则只能增加n-j个字符,所以最小的cost和为n-j;

关于选择的可能:

<1>复制:dp[i, j] = dp[i+1, j+1], 如果S[i]==D[j],可以使用复制操作;

<2>删除:dp[i, j] = dp[i+1, j] + 1,删除操作cost为1,删除S[i],子问题为dp[i+1, j];

<3>替换:dp[i, j] = dp[i+1, j+1] + 1,替换操作只能在S[i]与D[j]不相等时才能选择;

<4>增加:dp[i, j] = dp[i, j+1] + 1,同样的,增加操作cost为1;

则该问题的动态规划方程已经给出,可以求解该问题;

代码如下:

#include <cstdio>
#include <iostream>
using namespace std; const int MAX_N = + ;
char source[MAX_N], dest[MAX_N];
int dp[MAX_N][MAX_N]; inline int Min(int a, int b) { return a > b ? b : a; } int main()
{
int s_len, d_len; while(scanf("%d %s", &s_len, source) != EOF)
{
scanf("%d %s", &d_len, dest); memset(dp, , sizeof(dp));
for (int i = ; i <= d_len; ++i)
dp[s_len][i] = d_len - i;
for (int i = ; i <= s_len; ++i)
dp[i][d_len] = s_len - i;
for (int i = s_len - ; i >= ; --i)
{
for (int j = d_len - ; j >= ; --j)
{
int min_cost = ; min_cost = Min(min_cost, dp[i + ][j] + );
min_cost = Min(min_cost, dp[i][j + ] + );
if (source[i] == dest[j])
min_cost = Min(min_cost, dp[i + ][j + ]);
else
min_cost = Min(min_cost, dp[i + ][j + ] + );
dp[i][j] = min_cost;
}
}
printf("%d\n", dp[][]);
} return ;
}

poj 3356 AGTC(线性dp)的更多相关文章

  1. POJ 3356 AGTC(最小编辑距离)

    POJ 3356 AGTC(最小编辑距离) http://poj.org/problem?id=3356 题意: 给出两个字符串x 与 y,当中x的长度为n,y的长度为m,而且m>=n.然后y能 ...

  2. POJ 3356.AGTC

    问题简述: 输入两个序列x和y,分别执行下列三个步骤,将序列x转化为y (1)插入:(2)删除:(3)替换: 要求输出最小操作数. 原题链接:http://poj.org/problem?id=335 ...

  3. POJ 2479-Maximum sum(线性dp)

    Maximum sum Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 33918   Accepted: 10504 Des ...

  4. POJ 3356 AGTC(DP求字符串编辑距离)

    给出两个长度小于1000的字符串,有三种操作,插入一个字符,删除一个字符,替换一个字符. 问A变成B所需的最少操作数(即编辑距离) 考虑DP,可以用反证法证明依次从头到尾对A,B进行匹配是不会影响答案 ...

  5. POJ 1745 Divisibility (线性dp)

    Divisibility Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 10598   Accepted: 3787 Des ...

  6. POJ 3356 AGTC(DP-最小编辑距离)

    Description Let x and y be two strings over some finite alphabet A. We would like to transform x int ...

  7. POJ 3356 AGTC(最长公共子)

    AGTC Description Let x and y be two strings over some finite alphabet A. We would like to transform  ...

  8. POJ 3356(最短编辑距离问题)

    POJ - 3356 AGTC Time Limit: 1000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u Desc ...

  9. poj 1050 To the Max(线性dp)

    题目链接:http://poj.org/problem?id=1050 思路分析: 该题目为经典的最大子矩阵和问题,属于线性dp问题:最大子矩阵为最大连续子段和的推广情况,最大连续子段和为一维问题,而 ...

随机推荐

  1. C - 下沙小面的(2)

    C – 下沙小面的(2)Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64uSubmit StatusDes ...

  2. [C#技术参考]Socket传输结构数据

    最近在做一个机器人项目,要实时的接收机器人传回的坐标信息,并在客户端显示当前的地图和机器人的位置.当然坐标的回传是用的Socket,用的是C++的结构体表示的坐标信息.但是C#不能像C++那样很eas ...

  3. 利用merge存储引擎来实现分表

    我觉得这种方法比较适合,那些没有事先考虑,而已经出现了得,数据查询慢的情况.这个时候如果要把已有的大数据量表分开比较痛苦,最痛苦的事就是改代码,因为程序里面的sql语句已经写好了,现在一张表要分成几十 ...

  4. codeforces 633C. Spy Syndrome 2 hash

    题目链接 C. Spy Syndrome 2 time limit per test 2 seconds memory limit per test 256 megabytes input stand ...

  5. 编程习题——Maximum Subarray

    Find the contiguous subarray within an array (containing at least one number) which has the largest ...

  6. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">的含义

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/x ...

  7. 了解常见的浏览器内核 Trident,Geckos,Presto,Webkit

    了解常见的浏览器内核 Trident,Geckos,Presto,Webkit 内核只是一个通俗的说法,英文名称为"Layout engine",翻译过来就是"排版引擎& ...

  8. JSP打印九九乘法表

    ##index.jsp: <%@ page language="java" import="java.util.*" pageEncoding=" ...

  9. rails总结

    rails总结 注意:本文档以rails3.2版本为基础,并且用RubyMine 4.0.3作为ide 一.rails的结构与重要文件 Rails 是一个MVC库.同时,Rails的特点就是:惯用名优 ...

  10. WebGL是一种3D绘图标准,这种绘图技术标准允许把JavaScript和OpenGL ES 2.0结合在一起

    WebGL是一种3D绘图标准,这种绘图技术标准允许把JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenGL ES 2.0的一个JavaScript绑定,WebGL可以为HTM ...