经典dp 编辑距离

给定两个字符串S和T,对于T我们可以进行三种操作

(1)在任意位置增加字符

(2)删除字符

(3)替换字符

问最少多少次能把T变成S?

设f(i,j)是S的前i位和T的前j位对齐的最小花费

接下来分析每一位

(1)如果S[i]==T[j],就不用任何修改,那么最小花费是f(i-1,j-1)

(2)如果S[i]!=T[j],那么最小花费是f(i-1,j-1)+1

(3)如果S的前i位已经和T的前(j-1)位对齐了,那么最小花费是f(i,j-1)+1

(4)如果S的前(i-1)位已经和T的前j位对齐了,那么最小花费是f(i-1,j)+1

综上,递推式是f(i,j)=min(f(i,j)+cost,f(i-1,j)+1,f(i,j-1)+1)

最后分析一下初值:

f(i,0)=i

f(0,j)=j

这就相当与把S或T的前i或j位全部删除的样子(好残忍……)

 

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int f[1005][1005];
int main()
{
    char a[1005],b[1005];
    int lena,lenb,i,j,cost,mincost;
    while(~scanf("%s%s",a,b))
    {
        lena=strlen(a);
        lenb=strlen(b);
        for(i=0; i<lena; i++)
            f[i][0]=i;
        for(i=0; i<lenb; i++)
            f[0][i]=i;
        for(i=1; i<=lena; i++)
            for(j=1; j<=lenb; j++)
            {
                if(a[i-1]==b[j-1]) cost=0;
                else cost=1;
                mincost=min(f[i][j-1]+1,f[i-1][j]+1);
                f[i][j]=min(mincost,f[i-1][j-1]+cost);
            }
        printf("%d\n",f[lena][lenb]);
        memset(f,0,sizeof(f));
    }
    return 0;
}
View Code

 

posted @ 2016-03-05 09:34  良将ℓ  阅读(361)  评论(0编辑  收藏  举报