HJ52 计算字符串的编辑距离

提示:文章

文章目录

前言

前期疑问:
本文目标:


一、背景

最近

二 HJ52 计算字符串的编辑距离

2.1 题目

Levenshtein 距离,又称编辑距离,指的是两个字符串之间,由一个转换成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。编辑距离的算法是首先由俄国科学家 Levenshtein 提出的,故又叫 Levenshtein Distance 。

例如:

字符串A: abcdefg

字符串B: abcdef

通过增加或是删掉字符 ”g” 的方式达到目的。这两种方案都需要一次操作。把这个操作所需要的次数定义为两个字符串的距离。

要求:

给定任意两个字符串,写出一个算法计算它们的编辑距离。

数据范围:给定的字符串长度满足 1≤strlen(str)≤1000

输入描述:

每组用例一共2行,为输入的两个字符串

输出描述:

每组用例输出一行,代表字符串的距离

示例1

输入:

abcdefg
abcdef

复制

输出:

1

2.2 代码

2.2.1 第一版

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

#define STR_MAX_LEN 1001

int calculateLength(char* str1, char* str2)
{
    int len1 = strlen(str1);
    int len2 = strlen(str2);
    if(len1 < len2)
    {
        char temp[STR_MAX_LEN] = {'\0'};
        memcpy(temp, str1, len1 + 1);
        memcpy(str1, str2, len2 + 1);
        memcpy(str2, temp, len1 + 1);
    }

    len1 = strlen(str1);
    len2 = strlen(str2);

    int fast = len1 - 1;
    int slow = 0;
    int count = 0;
    while(str1[slow++] != str2[0])
    {
        count++;
    }
    while(str1[fast--] != str2[len2 - 1])
    {
        count++;
    }

    return count;
}

int main()
{
    char str1[STR_MAX_LEN] = {'\0'};
    char str2[STR_MAX_LEN] = {'\0'};
    while(fgets(str1, STR_MAX_LEN, stdin) != NULL)
    {
        strtok(str1, "\n");
        fgets(str2, STR_MAX_LEN, stdin);
        strtok(str2, "\n");
        int count  = calculateLength(str1, str2);
        printf("%d\n",count);
    }
}

上述代码的思路是默认一定存在字符串A除了两头跟字符串B不一样,字符串A中间的和字符串B一样。所以用的快慢指针两头逼近中间来计算长度值的。

2.2.1 问题

因为你题目只给出了一个示例,这一版是针对该示例的。但是还是出现了两个问题,主要针对calculateLength函数中。

第一个就是

if(len1 < len2)
{
    char temp[STR_MAX_LEN] = {'\0'};
    memcpy(temp, str1, len1);
    memcpy(str1, str2, len2);
    **memcpy(str2, temp, len1);**
}

上述代码中,调试发现当strlen(str1)< strlen(str2)时,经过对调,str1和str2中字符串一样。是因为

memcpy(str2, temp, len1)

cpp拷贝时,temp长度小于str2,导致str2中脏数据没有清空,改成加1方式:

memcpy(str2, temp, len1 + 1);

可以避免这个情况。

if(len1 < len2)
{
    char temp[STR_MAX_LEN] = {'\0'};
    memcpy(temp, str1, len1 + 1);
    memcpy(str1, str2, len2 + 1);
    **memcpy(str2, temp, len1 + 1);**
}

这个情况也是经常出现啊,还没有引起足够重视。

第二个问题就是

len1 = strlen(str1);
    len2 = strlen(str2);

    **int fast = len1**;
    int slow = 0;
    int count = 0;
    while(str1[slow++] != str2[0])
    {
        count++;
    }
    **while(str1[fast--] != str2[len2 - 1])**
    {
        count++;
    }

对于该行代码

**int fast = len1**;
...
**while(str1[fast--] != str2[len2 - 1])**

这边数组越界了,因为fast的值是字符串长度。

然后这个题目第一版是没有完全通过实例的,这个示例失败了

用例输入

ucyfsmg
zuixhuhyjgksyhqkjqxwylkoubykjxtcvkyqjpzgltbemmbmqibxxqpkgbvwbmjotixanvciibubglizmumcrjavakiygyuv

预期输出

91

示例输出

4

2.2.2 第二版

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

#define STR_MAX_LEN 1001

int calculateLengthVersionTwo(char* str1, char* str2)
{
    int len1 = strlen(str1);
    int len2 = strlen(str2);
    if(len1 < len2)
    {
        char temp[STR_MAX_LEN] = {'\0'};
        memcpy(temp, str1, len1 + 1);
        memcpy(str1, str2, len2 + 1);
        memcpy(str2, temp, len1 + 1);
    }

    len1 = strlen(str1);
    len2 = strlen(str2);
    int max = 0;
    int count = 0;
    for(int i = 0; i < len1; i++)
    {
        for(int j = 0; j < len2; j++)
        {
            if(str1[i] == str2[j])
            {
                int x = i;
                int y = j;

                while(str1[x++] == str2[y++])
                {
                    count++;
                }
            }
        }
        max = count > max ? count : max;
        count = 0;
    }

    return len1 - max;
}

int calculateLengthVersionThree(char* str1, char* str2)
{
    int len1 = strlen(str1);
    int len2 = strlen(str2);
    if(len1 < len2)
    {
        char temp[STR_MAX_LEN] = {'\0'};
        memcpy(temp, str1, len1 + 1);
        memcpy(str1, str2, len2 + 1);
        memcpy(str2, temp, len1 + 1);
    }

    len1 = strlen(str1);
    len2 = strlen(str2);
    int max = 0;
    int count = 0;
    int j = 0;
    for(j; j < len2; j++)
    {
        for(int i = 0; i < len1; i++)
        {
            if(str1[i] != '0' && str1[i] == str2[j])
            {
                j++;
                str1[i] = '0';
                count++;
            }
        }
    }

    return len1 - count;
}

int compare(const void*a, const void* b)
{
    return *(char*)a - *(char*)b;
}

int calculateLengthVersionFour(char* str1, char* str2)
{
    int len1 = strlen(str1);
    int len2 = strlen(str2);
    if(len1 < len2)
    {
        char temp[STR_MAX_LEN] = {'\0'};
        memcpy(temp, str1, len1 + 1);
        memcpy(str1, str2, len2 + 1);
        memcpy(str2, temp, len1 + 1);
    }


    len1 = strlen(str1);
    len2 = strlen(str2);
    qsort(str1, len1, sizeof(char), compare);
    qsort(str2, len2, sizeof(char), compare);
    int max = 0;
    int count = 0;
    int p1 = 0;
    int p2 = 0;
    int i = 0;
    for(i; i < len2; i++)
    {
        for(int j = 0; j < len1; j++)
        {
            if(str2[i] == str1[j])
            {
                count++;
                i++;
            }
        }
    }

    return len1 - count;
}

int calculateLengthVersionFive(char* str1, char* str2)
{
    int len1 = strlen(str1);
    int len2 = strlen(str2);
    if(len1 < len2)
    {
        char temp[STR_MAX_LEN] = {'\0'};
        memcpy(temp, str1, len1 + 1);
        memcpy(str1, str2, len2 + 1);
        memcpy(str2, temp, len1 + 1);
    }


    len1 = strlen(str1);
    len2 = strlen(str2);
    int max = 0;
    int count = 0;
    int p1 = 0;
    int p2 = 0;
    int i = 0;
    int j = 0;
    int index = 0;
    while(p2 < len2)
    {
        for(j; j < len1; j++)
        {
            if(str1[j] == str2[p2])
            {
                p2++;
                count++;
                index = j;
            }
        }
        p2++;
        j = index;
    }

    return len1 - count;
}

int main()
{
    char str1[STR_MAX_LEN] = {'\0'};
    char str2[STR_MAX_LEN] = {'\0'};
    while(fgets(str1, STR_MAX_LEN, stdin) != NULL)
    {
        strtok(str1, "\n");
        fgets(str2, STR_MAX_LEN, stdin);
        strtok(str2, "\n");
        int count  = calculateLengthVersionFive(str1, str2);
        printf("%d\n",count);
    }

}

上面的题目调试了好几版啊,但是还是觉得的很难弄

上面的代码可以通过下面的示例

“ucyfsmg”;

“zuixhuhyjgksyhqkjqxwylkoubykjxtcvkyqjpzgltbemmbmqibxxqpkgbvwbmjotixanvciibubglizmumcrjavakiygyuv”;

但是通过不了下面的示例

zikwvkijajpkaicihcffiemzexmwjjlyrylxcuoewdmpivudhmgkuodjaurazdjnlgtpwz
wpnmubqfsnmapqpufmmsphqehjplwjkqspnnpywsvvjilxbcfsrygbelquaalenvkruyltiwqcpdrxgstywaja

然后我就纳闷了,这个题目怎么这么难搞呢?是不是有什么算法啊,不然不应该这么难啊。

然后再仔细看一下这个题目是动态规划的。。。难怪难做,先记录一下

三、

3.1


总结

未完待续

  • 20
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值