动态规划-编辑距离

 

设A和B是2个字符串。要用最少的字符操作将字符串A转换为字符串B。这里所说的字符操作包括 (1)删除一个字符; (2)插入一个字符; (3)将一个字符改为另一个字符。 将字符串A变换为字符串B所用的最少字符操作数称为字符串A到 B的编辑距离,记为d(A,B)。 对于给定的字符串A和字符串B,计算其编辑距离 d(A,B)。

输入格式:

第一行是字符串A,文件的第二行是字符串B。

提示:字符串长度不超过2000个字符。

输出格式:

输出编辑距离d(A,B)

输入样例:

在这里给出一组输入。例如:

fxpimu
xwrs 

输出样例:

在这里给出相应的输出。例如:

5

一个字符串有三种操作方式:

1.替换:将字符串的任意一个字符改为另一种字符

2.删除:删除字符串中的任意一个字符

3.插入:添加一个字符在字符串的任意位置

给定两个字符串a、b,求最少操作的数量使两个字符串相等(即编辑距离)

 

设dp[i][j]表示字符串a、b的子串a[1~i]、b[1~j]的编辑距离

当i=0或j=0时,代表至少有一个空串,显然:

  dp[i][j]=max(i,j)

当a[i]=b[j]时,a[i]、b[j]直接排除不考虑,相当于a[1~i]、b[1~j]的编辑距离:

  dp[i][j]=dp[i-1][j-1]

当a[i]!=b[j]时,有多种情况:

  进行替换操作时,改变a[i]或b[j]使其与另一个相等,编辑距离加1,再加上a[1~i-1]、b[1~j-1]的编辑距离即:dp[i][j]=dp[i-1][j-1]+1

  进行删除操作时,删除a[i]或b[j],编辑距离加1再加上a[1~i-1]、b[1~j](或a[1~i]、b[1~j-1])的编辑距离即:dp[i][j]=dp[i-1][j]+1(或dp[i][j]=dp[i][j-1]+1)

  进行插入操作时,插入a[i+1]使a[i+1]=b[j](b[j+1]同样),编辑距离加1加a[1~i]、b[1~j-1](或a[1~i]、b[1~j-1])的编辑距离即:dp[i][j]=dp[i-1][j]+1(或dp[i][j]=dp[i][j-1]+1)

  可以看出删除和插入操作表达式是一样的

 

由于dp[i][j]和字符串a,b开始下标不同,所以if语句里是i-1、j-1

#include<iostream>
using namespace std;
int d[2001][2001];
int main()
{
    int n,m,i,j,k;
    string a,b;
    while(cin>>a>>b)
    {
        n=a.length();
        m=b.length();
        for(i=0;i<=n;i++)
            d[i][0]=i;
        for(j=0;j<=m;j++)
            d[0][j]=j;
        for(i=1;i<=n;i++)
            for(j=1;j<=m;j++)
            {
                k=min(d[i-1][j]+1,d[i][j-1]+1);
                if(a[i-1]!=b[j-1])d[i][j]=min(k,d[i-1][j-1]+1);
                else d[i][j]=min(k,d[i-1][j-1]);
            }
        cout<<d[n][m]<<'\n';
    }
    return 0;
}

posted on 2019-10-21 20:24  我的昵称里必须得有mt  阅读(139)  评论(0)    收藏  举报

导航