两个字符串的编辑距离、相似度求解

两个字符串的编辑距离、相似度求解


概念

  1. 字符串的编辑距离,是指利用字符操作,把字符串A转换成字符串B所需要的最少操作数
    。其中,字符操作包括以下3种:

    • 删除一个字符 delete a character
    • 插入一个字符 insert a character
    • 替换一个字符 replace a character
  2. 字符串的相似度则是指,在字符串的编辑距离+1的倒数。

解决思路

另dis[i][j]表示从字符串word1[i]到字符串word2[j]的编辑距离。
假设word1:michaelab;word2:michaelxy。
下面分别分析3种字符操作的编辑距离:
* 考虑添加操作,在word1[i]后插入word2[j]的字符,此处为’y’。操作完成后,word1为michaelaby,word2为michaelxy。
此时问题就转变为求michaelab到michaelx的最小编辑距离,即dis[i][j-1]。
即dis[i][j] = dis[i][j-1] + 1
* 考虑删除操作,在word1[i]后删除word1[i]的字符,即’b’。操作完成后,word1为michaela,word2为michaelxy
此时问题就转变为求michaela到michaelxy的最小编辑距离,即dis[i-1][j]。
即dis[i][j] = dis[i-1][j] + 1
* 考虑替换操作,将word1[i]处的字符’b’替换为word2[j]处的字符’y’。如果此时二者相等,则编辑距离不会增加。
此时问题:dis[i][j]=dis[i-1][j-1] + 1/0
*上述三者取使得dis[i][j]最小的操作,在进行逐字符比较操作后,
dis[len1][len2]即为所求*


此时可列出dis[i][j]的方程如下:
1. dis[i][j] = 0 i=0,j=0
2. dis[i][j] = i j = 0
3. dis[i][j] = j i = 0
4. dis[i][j] = min(dis[i][j-1] + 1,dis[i-1][j] + 1,dis[i-1][j-1] + 1/0)
i > 0,j > 0

代码


int findmin(int a, int b, int c)
{
  int ret = ((a < b) ? a : b);
  return ((ret < c) ? ret : c);
}
void geteditdist(const string& str1, const string& str2)
{
  int len1 = str1.length();
  int len2 = str2.length();

  /*int** dis = new int* [len1+1];*/
  int** dis = (int**)malloc(sizeof(int*)*(len1 + 1));

  for (int i = 0; i <= len1; i++)
  {
    dis[i] = (int*)malloc(sizeof(int)*(len2 + 1));
    /*dis[i] = new int[len2+1];*/
  }
  /*初始化数据*/
  for (int i = 0; i <= len1; i++)dis[i][0] = i;
  for (int j = 0; j <= len2; j++)dis[0][j] = j;

  for (int i = 1; i <= len1; i++)
  {
    for (int j = 1; j <= len2; j++)
    {
      /*开始计算3种方法,然后比较哪个产生的编辑距离小*/
      int add = dis[i][j - 1] + 1;
      int del = dis[i - 1][j] + 1;
      //判断dis[i][j]时需要判断str1[i-1]和str2[j-1]
      //因为i和j的起始坐标都为1
      int rep = dis[i - 1][j - 1] + ((str1[i-1] == str2[j-1]) ? 0 : 1);
      dis[i][j] = findmin(add, del, rep);
    }
  }
  cout < <dis[len1][len2] << endl;//编辑距离
  cout << "1/"<< (dis[len1][len2]+1) << endl;//相似度
  for (int i = 0; i <= len1; i++)
  {
    free(dis[i]);
  }
  free(dis);

}
int main(int argc, char* argv[])
{
  string s1, s2;
  while (cin >> s1 >> s2)
  {
    geteditdist(s1,s2);
  }
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值