zoukankan      html  css  js  c++  java
  • 编辑距离

    原文地址:编辑距离作者:写意

    一、问题描述

    设A和B是两个字符串。要用最少的字符操作将字符串A转换为字符串B。这里所说的字符操作包括:

     (1)删除一个字符;

     (2)插入一个字符;

     (3)将一个字符改为另一个字符;

     将字符串A变换为字符串B所用的最少字符操作数称为字符串A到B的编辑距离,记为d(A,B)。试设计一个有效算法,对任给的两个字符串A和B,计算出它们的编辑距离d(A,B)。

     

    二、分析解答

    设所给的两个字符串为A[1:m]和B[1:n]。定义D[i][j]=d(A[1:i],B[1,j])。单字符a,b间的距离定义为:

    d(a,b)=0 (a=b)

    d(a,b)=1(a!=b)

    考察从字符串A[1:i]到字符串B[1:j]的变换。可分成以下几种情况:
    (1)字符A[i]改为字符B[j];需要d(A[i],B[j])次操作。

    (2)删除字符A[i];需要1次操作。

    (3)插入字符B[j];需要1次操作。
    因此,D[i][j]可递归地计算如下。

    D[i][j]=min{D[i-1][j-1]+d(A[i],B[j]),D[i-1][j]+1,D[i][j-1]+1}。

     

    三、算法描述

    int dist(A[0…m-1],B[0…n-1])

    {

    int D[0…m,0…n]

    int i,j,cost

    对于i等于0至m

    D[i, 0]=i

    对于j等于0至n

    D[0,j]=j

    对于i等于1至m

        对于j等于1至n

           若 A[i-1]=B[j-1]则cost=0 否则 cost=1

            D[i][j]=min(D[i-1,j]+1,//删除

                        D[i,j-1]+1,//插入

                        D[i-1,j-1]+cost//替换

                         )

    返回d[m,n]

    }

     

    四、代码实现

    定义一个二维数组D[][]存储中间结果,如下图所示,为已经初始化后的情况。然后从D[1,1]开始从左到右,从上到下依次按填表,表的最后一个元素D[m,n]就是要求的最终结果。

     

    0

    1

    2

    3

    4

    5

    6

    0

    0

    1

    2

    3

    4

    5

    6

    1

    1

     

     

     

     

     

     

    2

    2

     

     

     

     

     

     

    3

    3

     

     

     

     

     

     

    4

    4

     

     

     

     

     

     

    5

    5

     

     

     

     

     

     

    6

    6

     

     

     

     

     

     

     

    #include<iostream>
    #include<string>
    using namespace std;
    int D[100][100];
    int dis[100];
    int min(int a,int b,int c)
    {
        return c<(a>b?b:a)?c:(a>b?b:a);
    }
    int dist(char * A,char * B)
    {
        int m=strlen(A);
        int n=strlen(B);
        int i,j;

        for(i=0;i<=m;++i)
        {
            D[i][0]=i;
        }
        for(j=0;j<=n;++j)
        {
            D[0][j]=j;
        }
        int cost;
        for(i=1;i<=m;++i)
        {
            for(j=1;j<=n;++j)
            {
                if(A[i-1]==B[j-1])
                    cost=0;
                else
                    cost=1;
                D[i][j]=min(D[i-1][j-1]+cost,D[i-1][j]+1,D[i][j-1]+1);
            }
        }
        return D[m][n];
    }
    int dist2(char * A,char * B)
    {
        int m=strlen(A);
        int n=strlen(B);
        int i,j;
        for(i=0;i<=n;++i)
            dis[i]=i;
        int cost;
        for(i=1;i<=m;++i)
        {
            int y=i-1;
            for(j=1;j<=n;++j)
            {
                int x=y;
                y=dis[j];
                int z=j>1?dis[j-1]:i;
                cost=A[i-1]==B[j-1]?0:1;
                dis[j]=min(x+cost,y+1,z+1);
            }
        }
        return dis[n];
    }
    int main(int argc, char* argv[])
    {    
        char * ch1="bcdefghijklmnopq";
        char * ch2="abcdefghijklmnopadfsafwe";
        cout<<dist(ch1,ch2)<<endl;
        cout<<dist2(ch1,ch2)<<endl;
        return 0;
    }


    五、优化方法

    从上面算法可以看出,该算法时间复杂性为0(m*n),空间复杂性为O(m*n)。同时可以看出,当对第i行进行填表时,只需要用到第i-1行的数据,因 此可以用一个一维数组dis[0…n]代替二维数组D[0…m,0…n],因此空间复杂性降为O(n)。实现代码如上面函数dist2()所示。

  • 相关阅读:
    MongoDB 释放磁盘空间 db.runCommand({repairDatabase: 1 })
    RK 调试笔记
    RK Android7.1 拨号
    RK Android7.1 移植gt9271 TP偏移
    RK Android7.1 定制化 itvbox 盒子Launcher
    RK Android7.1 双屏显示旋转方向
    RK Android7.1 设置 内存条作假
    RK Android7.1 设置 蓝牙 已断开连接
    RK Android7.1 进入Camera2 亮度会增加
    RK 3128 调触摸屏 TP GT9XX
  • 原文地址:https://www.cnblogs.com/nbalive2001/p/2756457.html
Copyright © 2011-2022 走看看