poj 3356 AGTC 【編輯距離】

題意:

給你兩個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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章