uva 164 String Computer

DP(经典题):字符串最短编辑距离

关于计算最短编辑距离的资料有很多,这里不详说,这题还要求输出路径,并且注意到是实时的输出,关键在于输出中的那个数字,即位置

代码中已经有详细分析

 

/*
dp[i][j]表示a串前i个字符和b串前j个字符的最短编辑距离
1.dp[i][j]=dp[i-1][j]+1 即先删除a串的第i个字符,然后使其前i-1个字符与b串的前j个字符相同
2.dp[i][j]=dp[i][j-1]+1 即先让a串的前i个字符和b串的前j-1个字符相同,然后再在a串后面插入b[j]这个字符
3.dp[i][j]=dp[i-1][j-1]+(a[i]==b[j]?0:1) 
  即先让a串前i-1个字符和b串前j-1个字符相同,看a[i]是否等于b[j],等于的话不需要操作,不等让a[i]变为b[j]
dp[i][j]=min{1,2,3}
最后来解决一下如何保存路径的问题,p[i][j]=1,2,3,表示得到dp[i][j]的时候是用了第几个策略
p[i][j]=1,说明用了策略1,是删除了a[i],所以输出删除对应的语句,注意此时对应的位置是j+1,并接着去到p[i-1][j]
p[i][j]=2,说明用了策略2,是插入了b[j],所以输出插入对应的语句,注意此时对应的位置是j,并接着去到p[i][j-1]
p[i][j]=0,说明用了策略3,但没有更换,不用输出,并接着去到p[i-1][j-1]
p[i][j]=3,说明用了策略3,是更换了a[i],所以输出更换对应的语句,注意此时对应的位置是j,并接着去到p[i-1][j-1]
p数组初始化为-1,p[i][j]=-1,则说明路径到达了尽头,或者(i==0 && j==0)也是尽头标志,表示a串和b串都已经递归处理完
*/
#include <cstdio>
#include <cstring>
#define N 25
#define INF 0x3f3f3f3f

char a[N],b[N];
int dp[N][N],p[N][N];

int min(int i ,int j ,int *s)
{
    int f,k;
    for(k=1; k<=3; k++)
        if(s[k]<dp[i][j])
        { dp[i][j]=s[k]; f=k; }
    if(f==3 && a[i]==b[j]) f=0;
    return f;
}

void print(int i ,int j)
{
    
    if(!i && !j) return ;
    else if(p[i][j]==1) //删除a串第i个字符
    {
        print(i-1,j);
        printf("D%c%02d",a[i],j+1);
        return ;
    }
    else if(p[i][j]==2) //在a串最后(第i个字符后)插入字符b[j]
    {
        print(i,j-1);
        printf("I%c%02d",b[j],j);
        return ;
    }
    else if(p[i][j]==0) //什么都不做
    {
        print(i-1,j-1);
        return ;
    }
    else //把a[i]变为b[j]
    {
        print(i-1,j-1);
        printf("C%c%02d",b[j],j);
        return ;
    }
}

int main()
{
    int lena,lenb;
    while(1)
    {
        scanf("%s",a+1); 
        if(a[1]=='#') break;
        scanf("%s",b+1);
        lena=strlen(a+1); lenb=strlen(b+1);
        memset(dp,0x3f,sizeof(dp));
        memset(p,-1,sizeof(p));
        for(int i=0; i<=lena; i++) { dp[i][0]=i; p[i][0]=1; }
        for(int i=0; i<=lenb; i++) { dp[0][i]=i; p[0][i]=2; }
        //dp[1][1]=(a[1]==b[1]?0:1);

        for(int i=1; i<=lena; i++)
            for(int j=1; j<=lenb; j++)
            {
                int s[4];
                s[1]=dp[i-1][j]+1;
                s[2]=dp[i][j-1]+1;
                s[3]=dp[i-1][j-1]+(a[i]==b[j]?0:1);
                p[i][j]=min(i,j,s);
            }
        //printf("最短编辑距离:%d\n",dp[lena][lenb]);
        print(lena ,lenb);
        printf("E\n");
    }
    return 0;
}

 

posted @ 2013-02-25 15:25  Titanium  阅读(724)  评论(0编辑  收藏  举报