您的位置:首页 > 其它

poj 3356 AGTC 【编辑距离】

2013-08-13 00:15 465 查看
题意:

给你两个DNA序列,长度小于1000 ,同时定义了三种编辑操作:1. 将任意一个字符删除 2. 在任意位置添加一个字符 3. 将任意一个字符替换成令一个字符。

问:将第一个DNA序列变成第二个最少需要多少次操作。

解法:

经典DP问题,编辑距离,模板题, O(n2)。

状态:

dp[i][j] 表示由前一个字符串的前i个变成后一个字符串的前j个字符所需的最少次数。

转移方程:

a[i] == b[j] -> dp[i][j] = min(dp[i-1][j]+1, dp[i][j-1]+1, dp[i-1][j-1])

a[i] != b[j] -> dp[i][j] = min(dp[i-1][j]+1, dp[i][j-1]+1, dp[i-1][j-1]+1)

dp[i-1][j]转移来的含义是在a的当前位置插入一个字符,d[i][j-1]则是要在a的当前字符删掉,dp[i-1][j-1]转移来则是要进行字符替换,若当前的两个字符相等,操作便不会增加,转移的结果取最少的。

初始化:

dp[i][0] = i , dp[0][j] = j

由于任何空串转化成别的串一定要进行串长度次添加,同理,变为空串需要一定步数的删除操作。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
using namespace std;

const int maxn = 1e3+5;
int dp[maxn][maxn];

int main(){
string a,b;
int la,lb;
while(cin >> la >> a){
cin >> lb >> b;
a = "$" + a;
b = "$" + b;
memset(dp, 0 , sizeof(dp));
for(int i = 0 ; i <= la ; i++){
dp[i][0] = i;
}
for(int j = 0 ; j <= lb ; j++){
dp[0][j] = j;
}
for(int i = 1 ; i <= la ; i++){
for(int j = 1; j <= lb ; j++) {
dp[i][j] = min(dp[i-1][j]+1, min(dp[i][j-1]+1, dp[i-1][j-1]+(a[i]!=b[j])));
}
}
cout << dp[la][lb] << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: