Levenshtein Edit distance

似乎在LeetCode里面也有,不过这里是为了解决另外的问题而做的。假设两个string,有三种不同的操作:添加,删除,替换。如何通过最少步骤让一个字符串变换成为另一个字符串?这个最少步骤数即为Levenshtein edit distance。做法是用动态规划,见http://en.wikipedia.org/wiki/Edit_distance


#include <cassert>
#include <iostream>
#include <memory>
#include <string>

int edit_distance(const std::string& s1, const std::string& s2) {
    const int s1_length = s1.length();
    const int s2_length = s2.length();
    const int s1_elems = s1_length + 1;
    const int s2_elems = s2_length + 1;
    const int total_elems = s1_elems * s2_elems;
    std::unique_ptr<int[]> distance_matrix(new int[total_elems]);

    auto access = [&distance_matrix, s1_elems, s2_elems](int index_s1, int index_s2) -> int& {
        assert(index_s1 >= 0 && index_s1 < s1_elems);
        assert(index_s2 >= 0 && index_s2 < s2_elems);
        return distance_matrix[index_s2 * s1_elems + index_s1];
    };


    std::fill(distance_matrix.get(), distance_matrix.get() + total_elems, 0);

    for(auto i = 0; i < s1_elems; ++i)
        access(i, 0) = i;
    for(auto i = 0; i < s2_elems; ++i)
        access(0, i) = i;

    // Note: the iterator starts from 0, but when we map it to the matrix, the
    // index should be increased by 1
    for(auto s1_iter = 0; s1_iter < s1_length; ++s1_iter)
        for(auto s2_iter = 0; s2_iter < s2_length; ++s2_iter) {
            const char s1_ch = s1[s1_iter];
            const char s2_ch = s2[s2_iter];

            if (s1_ch == s2_ch) {
                access(s1_iter + 1, s2_iter + 1) = access(s1_iter, s2_iter);
            }
            else {
                access(s1_iter + 1, s2_iter + 1) = std::min(std::min(
                            access(s1_iter + 1, s2_iter),
                            access(s1_iter, s2_iter + 1)),
                        access(s1_iter, s2_iter)) + 1;
            }
        }

    return access(s1_length, s2_length);
}

int main(int argc, char* argv[]) {
    if (argc != 3) {
        std::cerr<<"Usage: edit_distance [string1] [string2]"<<std::endl;
        return -1;
    }
    std::cout<<edit_distance(argv[1], argv[2])<<std::endl;
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值