动态规划法求解距离字符串问题

/*

题目:
设有字符串X,我们称在X的头尾及中间插入任意多个空格后构成的新字符串为X的扩展串,
    如字符串X为"abcbcd",则字符串"abcb□cd","□a□bcbcd□"和"abcb□cd□"都是X的扩展串,
这里"□"代表空格字符。
 如果A1是字符串A的扩展串,B1是字符串B的扩展串,A1与B1具有相同的长度,
那么我扪定义字符串A1与B1的距离为相应位置上的字符的距离总和,而两个非空格
字符的距离定义为它们的ASCII码的差的绝对值,而空格字符与其他任意字符之间的
距离为已知的定值K,空格字符与空格字符的距离为0。在字符串A、B的所有扩展串中,
必定存在两个等长的扩展串A1、B1,使得A1与B1之间的距离达到最小,我们将这一距离定义为字符串A、B的距离。
*/

给出最优子结构:

函数D()为两个字符或字符串的距离
函数L()为字符串的长度
K为空格字符与非空格字符的长度

D(str1,str2) =
    L(str1)*K 当str1非空串,str2空串
    L(str2)*K 当str2非空串,str1空串
    min(D(str1[1],str2[1])+D(str1[2...n],str2[2...n]), K+D(str1,str2[2...n]), K+D(str1[2...n],str2))


#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "math.h"

#define K 2/*空格与其他字符的距离*/

char A[101];/*字串A*/
char B[101];/*字串B*/
char extendA[201];/*字串A的扩展串*/
char extendB[201];/*字串B的扩展串*/
int distance[101][101];/*记录字串的距离*/
int construct[101][101];/*用于构造A,B的扩展字符串*/

/*比较三个数的大小,返回最小那个数的下标(从0开始)*/
int GetMinIndex (int a, int b, int c)
{
    if (a < b)
    {
        if (c < a)
            return 2;
        else
            return 0;
    }
    else/*b<=a*/
    {
        if (c < b)
            return 2;
        else
            return 1;
    }
}

/*按照规则返回两个字符的距离*/
int GetCharDistance (char a, char b)
{
    if ((a==32&&b!=32) || (a!=32&&b==32))
        return K;
    else
        return abs(a-b);
}

/*求解并打印两个字符串的距离*/
void GetStrDistance (char* A, char* B)
{
    int i, j, p, temp[3], minIndex, dir;
    int m = strlen(A);
    int n = strlen(B);
   
    /*初始化*/
    for (i=0; i<=m; i++)
        distance[i][0] = i*K;
    for (j=0; j<=n; j++)
        distance[0][j] = j*K;
    extendA[200] = '/0';
    extendB[200] = '/0';
   
    /*自底向上求解*/      
    for (i=1; i<=m; i++)
        for (j=1; j<=n; j++)
        {
            /*注意字符串的下标和表格的下标*/
            temp[0] = GetCharDistance(A[i-1], B[j-1]) + distance[i-1][j-1];
            temp[1] = GetCharDistance(A[i-1], ' ') + distance[i-1][j];
            temp[2] = GetCharDistance(' ', B[j-1]) + distance[i][j-1];
            construct[i][j] = minIndex = GetMinIndex(temp[0], temp[1], temp[2]);
            distance[i][j] = temp[minIndex];
        }
   
    /*从后往前构造扩展字符串*/
    i = m;;
    j = n;
    p = 199;
    while (i>0 || j>0)
    {
        dir = construct[i][j];
        if (dir == 0)
        {
            extendA[p] = A[--i];
            extendB[p] = B[--j];
        }
        else if (dir == 1)
        {
            extendA[p] = A[--i];
            extendB[p] = ' ';
        }
        else
        {
            extendA[p] = ' ';
            extendB[p] = B[--j];
        }
        p--;
    }
   
    /*移动字符串*/
    for (i=0; i<200-p; i++)
    {
        extendA[i] = extendA[i+p+1];
        extendB[i] = extendB[i+p+1];
    }
   
    /*打印距离与A,B的扩展字串*/
    printf("The distance of %s and %s is %d/n", A, B, distance[m][n]);
    printf("The extend-string of A is:");
    for (i=0; i<200-p-1; i++)
        printf("%c",extendA[i]);
    printf("/n");
    printf("The extend-string of B is:");
    for (i=0; i<200-p-1; i++)
        printf("%c",extendB[i]);
}
 
int main ()
{
    printf("Please input the two strings the length of which are shorter than 101:/n");
    printf("String A is: ");
    scanf("%s", A);
    printf("String B is: ");
    scanf("%s", B);
    GetStrDistance(A, B);
 
    system("pause");
    return 0;
}
 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值