动态规划:字符串的编辑距离

参考书目:《算法的乐趣》作者王晓华

算法的乐趣 

参考博文:两个字符串的编辑距离-动态规划方法

动态规划是解决多阶段决策问题常用的最优化理论,由美国数学家Bellman等人在1957年提出,用于研究多阶段决策过程的优化问题。

适合求解多阶段(状态转移)决策问题的最优解,也可用于含线性问题或非线性递推关系的最优解问题。需满足以下两个特性。

最优化原理:不管之前的决策是否是最优决策,都必须保证从现在开始的决策是在之前决策基础上的最优决策。

无后向性(无后效性):每个阶段的决策仅受之前决策的影响,但是不影响之后各阶段的决策。


一般有四个步骤:定义最优子问题->定义状态->定义决策和状态转换方程->确定边界条件

两个字符的相似度定义为:将一个字符串转换成另一个字符串时需要付出的代价。其中,字符串的操作包括以下三种:

  • 删除一个字符     a) Insert a character
  • 插入一个字符     b) Delete a character
  • 修改一个字符     c) Replace a character

首先用朴素的递归算法实现

/*
2018-3-22
朴素的递归算法实现:字符串的编辑距离
copyright @GCN
*/

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int min(int a,int b)
{
    if(a>b)
        return b;
    else
        return a;
}

int EditDistance(char *src,char *dest)
{
    if(strlen(src)==0||strlen(dest)==0)
        return abs(strlen(src)-strlen(dest));
    if(src[0]==dest[0])
        return EditDistance(src+1,dest+1);
    int edIns=EditDistance(src,dest+1)+1;//source insert
    int edDel=EditDistance(src+1,dest)+1;//source delete
    int edRep=EditDistance(src+1,dest+1)+1;//source replace
    return min(min(edIns,edDel),edRep);
}

int main()
{
    char *src="SNOWY";
    char *dest="sunny";
    int cost;
    cost=EditDistance(src,dest);
    printf("the final answer is %d\n",cost);
    return 0;
}


(发现两次结果不一样,还以为写错了。呃,原来是我输入的字符串的大小写问题。)

然后用动态规划对朴素的递归算法进行改进

/*
2018-3-23
动态规划:字符串的编辑距离
copyright @GCN
*/

#define MAX_STRING_LEN 100
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int min(int a,int b)
{
    if(a<b)
        return a;
    else
        return b;
}

int EditDistance(char *src,char *dest)
{
    int i,j;
    int d[MAX_STRING_LEN][MAX_STRING_LEN]={0xFFFF};
    int edIns,edDel,edRep;

    for(i=0;i<=strlen(src);i++)
        d[i][0]=i;
    for(j=0;j<=strlen(dest);j++)
        d[0][j]=j;
    for(i=1;i<=strlen(src);i++)
    {
        for(j=1;j<=strlen(dest);j++)
        {
            if((src[i-1]==dest[j-1]))
                d[i][j]=d[i-1][j-1];//字符匹配,不需要任何操作
            else
            {
                edIns=d[i][j-1]+1;//source 插入字符
                edDel=d[i-1][j]+1;//source 删除字符
                edRep=d[i-1][j-1]+1;//source 替换字符

                d[i][j]=min(min(edIns,edDel),edRep);
            }
        }
    }
    return d[strlen(src)][strlen(dest)];
}

int main()
{
    char *src="SNOWY";
    char *dest="SUNNY";

    int cost=EditDistance(src,dest);
    printf("the final result is %d\n",cost);
    return 0;
}



猜你喜欢

转载自blog.csdn.net/jesmine_gu/article/details/79667549