提示:文章
文章目录
前言
前期疑问:
本文目标:
一、背景
最近
二 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
总结
未完待续