[经典算法] 字符串相似度-编辑距离

题目说明:

一种衡量两个字符串之间的差异性的方法是,计算两个字符串转换时候需要的最少操作,需要的操作越少说明这两个字符串越相似。

 

题目解析:

假设字符串的操作只有三种:

  1. 插入一个字符;
  2. 删除一个字符;
  3. 替换一个字符;

两个字符串之间的编辑距离定义为:从字符串str1到str2的最少的操作次数。首先,编辑距离是不会大于str1.length + str2.length的。假设求字符A、B的编辑距离,考虑下面几种情况:

  • 如果A[i] = B[j],那么这时候还需要操作吗?

     这个时候的删除和替换操作只会让情况变得更坏,而且插入操作不会使情况变得更好,所以此时F(i, j) = F(i-1, j-1)。

  • 如果A[i] != B[j],怎么办呢?

     a、从F(i-1, j-1)变过来,这时候只需要把A[i]替换为B[j]即可;

     b、从F(i-1, j)变过来,这时候只需要将A[i]删除即可;

     c、从F(i, j-1)变过来,这时候只需要在A[i]后插入字符B[j]即可;

     那么此时,F(i, j) = min{F(i-1,j-1),F(i-1,j),F(i,j-1)} + 1。

   注:其中F(i, j)表示A[0..i]和B[0..j]之间的编辑距离。

 

程序代码:

#include <gtest/gtest.h>
#include <iostream>
#include <string>
using namespace std;

int CalcDistance(const string& A, int offsetA,const string& B, int offsetB)
{
    if (A.size() == offsetA)
    {
        return B.size() - offsetB;        
    }

    if (B.size() == offsetB)
    {
        return A.size() - offsetA;
    }

    if (A[offsetA] == B[offsetB])
    {
        return CalcDistance(A, offsetA+1, B, offsetB + 1);
    }
    else
    {
        int dist1 = CalcDistance(A, offsetA, B, offsetB + 1);
        int dist2 = CalcDistance(A, offsetA + 1, B, offsetB);
        int dist3 = CalcDistance(A, offsetA + 1, B, offsetB + 1);
        int result = dist1 < dist2 ? dist1 : dist2;
        result = result < dist3 ? result : dist3;

        return result + 1;
    }
}

int main_modify()
{
    return 0;
}

TEST(BaiLian, tLevenshtein)
{        
    ASSERT_EQ(CalcDistance("zero",0,"ero",0), 1);
    ASSERT_EQ(CalcDistance("zero",0,"fero",0), 1);
    ASSERT_EQ(CalcDistance("abcddefg",0,"abcefg",0), 2);
    ASSERT_EQ(CalcDistance("abcddefg",0,"abcddefg",0), 0);
    ASSERT_EQ(CalcDistance("abcddfg",0,"abcddefg",0), 1);
    ASSERT_EQ(CalcDistance("",0,"",0), 0);
    ASSERT_EQ(CalcDistance("abcdefgh",0,"",0), 8);
    ASSERT_EQ(CalcDistance("",0,"abcdefgh",0), 8);
}

参考引用

http://www.cnblogs.com/tianchi/archive/2013/02/25/2886964.html

原文地址:https://www.cnblogs.com/Quincy/p/4748621.html