DP-编辑距离问题

【题意】设A和B是2个字符串。要用最少的字符操作将字符串A转换为字符串B。这里所说的字符操作包括
(1)删除一个字符;
(2)插入一个字符;
(3)将一个字符改为另一个字符。
将字符串A变换为字符串B所用的最少字符操作数称为字符串A到B的编辑距离,记为d(A,B)。试设计一个有效算法,对任给的2个字符串A和B,计算出它们的编辑距离d(A,B)。
【例如】
S=abcd T=ef,dis(S,T)=4;
S=AGTCTGACGC T=AGTAAGTAGGC, dis(S,T)=4;
【思路】
分析最优解结构
设字符串 A=a1,a2,…am B=b1, b2,… bn ;d[i][j] 用于记录字符串Ai到字符串B j的最短编辑距离,其中Ai = a1,a2 …ai , Bj = b1, b2… bj
Ai到Bj的最短编辑距离可以分解为三个子题 :即求Ai-1 到Bj-1 ,Ai 到Bj-1 ,Ai-1 到Bj的最
短编辑距离,通过修改,增加,删除一个字符得到;从这三种方式中选择编辑距离最短的一个就是Ai到Bj的最短编辑距离。
显然可知计算d[i][j]的一个最优解所包含的计算d[i-1][j-1], d[i][j-1], d[i-1][j]也是最优的。
算法设计思路:
编辑距离问题具有最优子结构性质。

现在要将a1,a2 …ai-1,ai转换为b1, b2 ,… bj-1,bj 则可以分为以下几种情况进行讨论:

 (1)如果ai = bj  ,则 Ai = Bj 
    (2)如果ai ≠ bj ,则 有三种方式将a1,a2 …ai-1,ai转换为b1, b2 ,… bj-1,bj 。

【1】将ai修改为bj,使求Ai到Bj的最短编辑距离问题转化为求 Ai-1: a 1,a2 …ai-1到Bj-1:b1, b2 ,… bj-1的最短编辑距离问题。

【2】通过删除 ai,使求Ai到Bj的最短编辑距离问题转化为求Ai-1: a 1,a2 …ai-1到 Bj:b1, b2 ,… bj-1, bj 的最短编辑距离问题。

【3】通过增加 ai,使求Ai到Bj的最短编辑距离问题转化为求Ai: a 1,a2 …ai-1,ai到 Bj-1:b1, b2 ,… bj-1, 的最短编辑距离问题。
例如:
( 1 ) a4 = b3
bcde -> dfe -> bcd -> df
( 2 ) a4 ≠ b3 bcdg ->dfk
i ) 在bcdg 末尾增加k 得到 bcdgk
bcdg -> dfk -> bcdg+k bcdg -> df
ii ) 删除bcdg 末尾字符g 得到 bcd
bcdg -> dfk -> bcd bcd -> dfk
iii) 将bcdg末尾字符g修改为 k , 得到bcdk
bcdg -> dfk -> bcdk bcd -> df
子问题的递归结构
由编辑距离的最优子结构性质可知,要找出字符串A到字符串B的最短编辑距离,可以按照通过递归来实现。可以建立递归关系如下:
这里写图片描述
设置边界值
d[0][i] = i (0 < i < n)
d[j][0] = j (0 < j < m)

问题的时间复杂性:算法耗时 O(mn )
代码如下:

/***************************
DP-编辑距离问题
Author:herongwei
Time:2017/1/24 17:10
language:C++
***************************/
#pragma comment(linker,"/STACK:102400000,102400000")
//#include <bits/stdc++.h>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 1e3+10;
const int maxm = 1e3+10;
const LL MOD = 999999997;
int dir4[4][2]= {{1,0},{0,1},{-1,0},{0,-1}};
int dir8[8][2]= {{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1}};
inline LL read(){
    int  c=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
    return c*f;
}
inline int minn(int a,int b,int c){
return  min(min(a,b),c);
}
inline int maxx(int a,int b,int c){
return max(a,max(b,c));
}
char S[maxn],T[maxn];
int dp[maxn][maxn];
int sl,tl;
///dp[i][j]表示S[0..i]和T[0..j]的最短编辑距离
int Edit_Distance()
{
    memset(dp,0,sizeof(dp));
    for(int i=1; i<=max(sl,tl); ++i){
        dp[i][0]=dp[0][i]=i;
    }
    for(int i=1; i<=sl; ++i){
        for(int j=1; j<=tl; ++j){
           int tp=1;
           if(S[i]==T[j]) tp=0;
           dp[i][j]=minn(dp[i-1][j-1]+tp,dp[i-1][j]+1,dp[i][j-1]+1);
        }
    }
    printf("%d\n",dp[sl][tl]);
}
int main()
{
   // freopen("in.txt","r",stdin);
    while(scanf("%d %s %d %s",&sl,S+1,&tl,T+1)!=EOF)
    {
        Edit_Distance();
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值