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;

}

 

你可能感兴趣的:(String)