小言_互联网的博客

基础算法:编辑距离

356人阅读  评论(0)

编辑距离又称莱文斯坦距离,是俄国数学家Vladimir Levenshtein在1965年所提出的概念,主要用来判断对于两个字符串的差异化的量化,确认需要多少次处理才能将一个字符串变为另外一个,处理一般分为添加、删除和替换三种。

常见的使用场景

编辑距离在自然语言处理中国可以用于拼写检查,也可以用于DNA之间生物信息之间类似程度的判断,而unix下的diff等命令也是利用编辑距离算法进行文本编辑对比。

示例代码

这里使用最简单的C语言方式进行模拟,效率虽然很低,递归写法是最简洁的,只需要如下即可实现简单的编辑距离的计算:

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

#define MAX_STRING_LENGTH 100

int min(int a, int b, int c) {
   
    int min = a > b ? b : a;
    return min > c ? c : min;
}

int distance(char* src, char* dst, int src_cnt, int dst_cnt) {
   
    if (src_cnt == -1) return dst_cnt + 1;
    if (dst_cnt == -1) return src_cnt + 1;

    if(src[src_cnt] == dst[dst_cnt]) {
   
        return distance(src, dst, src_cnt-1, dst_cnt-1);
    } else {
   
        return min(distance(src, dst, src_cnt-1, dst_cnt) + 1,
                   distance(src, dst, src_cnt, dst_cnt-1) + 1,
                   distance(src, dst, src_cnt-1, dst_cnt-1) + 1);
    }
}

int main(void) {
   
    char src[MAX_STRING_LENGTH] = {
    0 };
    char dst[MAX_STRING_LENGTH] = {
    0 };
    int  src_cnt = 0, dst_cnt = 0;

    while(scanf("%s",src) != EOF) {
   
        scanf("%s",dst);

        src_cnt = strlen(src);
        dst_cnt = strlen(dst);
        printf("%d\n",distance(src, dst, src_cnt, dst_cnt));
    }
}

结果确认

优化

上述代码理解起来清楚地多,而且也较为简洁,但是由于存在重复路径问题,整体时间复杂度较高,一般较难满足需求,所以这时一般需要使用动态规划表进行优化,比如本文可以使用如下方式进行优化(请注意此处仅为示例,大小和边界请自行确认)

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

#define MAX_STRING_LENGTH 100
#define DP_ARRAY_SIZE     100
int dp[DP_ARRAY_SIZE][DP_ARRAY_SIZE] = {
    0 };

int min(int a, int b, int c) {
   
    int min = a > b ? b : a;
    return min > c ? c : min;
}

void set_dp(char* src, char* dst, int src_cnt, int dst_cnt) {
   
    for ( int i=0; i<=src_cnt; i++) dp[i][0] = i;
    for ( int i=0; i<=dst_cnt; i++) dp[0][i] = i;

    for (int i=1; i<=src_cnt; i++) {
   
        for ( int j=1; j<=dst_cnt; j++) {
   
            if(src[i-1] == dst[j-1]) {
   
                dp[i][j] = dp[i-1][j-1];
            } else {
   
                dp[i][j] = min(dp[i-1][j]+1,dp[i][j-1]+1,dp[i-1][j-1]+1);
            }
        }
    }
}

void clear_dp() {
   
    for (int i=0; i<DP_ARRAY_SIZE; i++) {
   
        for (int j=0; j<DP_ARRAY_SIZE; j++) {
   
            dp[i][j] = 0;
        }
    }
}


int main(void) {
   
    char src[MAX_STRING_LENGTH] = {
    0 };
    char dst[MAX_STRING_LENGTH] = {
    0 };
    int  src_cnt = 0, dst_cnt = 0;

    while(scanf("%s",src) != EOF) {
   
        scanf("%s",dst);

        src_cnt = strlen(src);
        dst_cnt = strlen(dst);
        clear_dp();
        set_dp(src, dst, src_cnt, dst_cnt);
        printf("%d\n",dp[src_cnt][dst_cnt]);
    }
}

转载:https://blog.csdn.net/liumiaocn/article/details/108954376
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场