poj 3356 AGTC(线性dp)
题目链接: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)的更多相关文章
- POJ 3356 AGTC(最小编辑距离)
POJ 3356 AGTC(最小编辑距离) http://poj.org/problem?id=3356 题意: 给出两个字符串x 与 y,当中x的长度为n,y的长度为m,而且m>=n.然后y能 ...
- POJ 3356.AGTC
问题简述: 输入两个序列x和y,分别执行下列三个步骤,将序列x转化为y (1)插入:(2)删除:(3)替换: 要求输出最小操作数. 原题链接:http://poj.org/problem?id=335 ...
- POJ 2479-Maximum sum(线性dp)
Maximum sum Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 33918 Accepted: 10504 Des ...
- POJ 3356 AGTC(DP求字符串编辑距离)
给出两个长度小于1000的字符串,有三种操作,插入一个字符,删除一个字符,替换一个字符. 问A变成B所需的最少操作数(即编辑距离) 考虑DP,可以用反证法证明依次从头到尾对A,B进行匹配是不会影响答案 ...
- POJ 1745 Divisibility (线性dp)
Divisibility Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 10598 Accepted: 3787 Des ...
- POJ 3356 AGTC(DP-最小编辑距离)
Description Let x and y be two strings over some finite alphabet A. We would like to transform x int ...
- POJ 3356 AGTC(最长公共子)
AGTC Description Let x and y be two strings over some finite alphabet A. We would like to transform ...
- POJ 3356(最短编辑距离问题)
POJ - 3356 AGTC Time Limit: 1000MS Memory Limit: 65536KB 64bit IO Format: %I64d & %I64u Desc ...
- poj 1050 To the Max(线性dp)
题目链接:http://poj.org/problem?id=1050 思路分析: 该题目为经典的最大子矩阵和问题,属于线性dp问题:最大子矩阵为最大连续子段和的推广情况,最大连续子段和为一维问题,而 ...
随机推荐
- Javascript获取浏览器版本
前两天有朋友请教我这个问题,说现在网上的资料太过于混乱不完整,我这里先简单整理一部分. 0 (function(){ 1 2 var ver = window.navigator.userAgen ...
- CKEditor + CKFinder 实现编辑上传图片配置
下载最新版 ckfinder 本人下载的php版本 https://cksource.com/ckfinder/download 下载最新版ckeditor http://ckeditor.com/ ...
- *max_element函数和*min_element函数
C++中*max_element(v.begin,v.end)找最大元素*min_element(v.begin,v.end)找最小元素. 数组: #include<iostream> # ...
- gmpy2安装使用方法
GMP(GNU Multiple Precision Arithmetic Library,即GNU高精度算术运算库),它是一个开源的高精度运算库,其中不但有普通的整数.实数.浮点数的高精度运算,还有 ...
- glib源码安装使用方法
glib库是GTK+和GNOME工程的基础底层核心程序库,是一个综合用途的实用的轻量级的C程序库,它提供C语言的常用的数据结构的定义.相关的处理函数,有趣而实用的宏,可移植的封装和一些运行时机能,如事 ...
- JSWING小工具
项目中需要一个发送指令到指定服务端,取得设备ID及检测数据的小工具,就利用jswing开发了一个简单小组件,最终效果如下: 代码很简单,具体片段如下: Window.java import java. ...
- mysql null值问题
mysql> create table test( sn int, -> `createdTime` datetime NOT NULL COMMENT '创建时间', -> `up ...
- Javascript 思维导图
学习的道路就是要不断的总结归纳,好记性不如烂笔头,so,下面将po出8张javascript相关的思维导图. 思维导图小tips:思维导图又叫心智图,是表达发射性思维的有效的图形思维工具 ,它简单却又 ...
- CodeForces 235C Cyclical Quest(后缀自动机)
[题目链接] http://codeforces.com/contest/235/problem/C [题目大意] 给出一个字符串,给出一些子串,问每个子串分别在母串中圆环匹配的次数,圆环匹配的意思是 ...
- oralce dg conf
http://wenku.baidu.com/view/ea9fa16cdd36a32d73758168.html http://ylw6006.blog.51cto.com/470441/84181 ...