zoukankan      html  css  js  c++  java
  • 编辑距离问题

    本文来自于:http://www.cnblogs.com/biyeymyhjob/archive/2012/09/28/2707343.html

    编辑距离,又称Levenshtein距离,是指两个字串之间,由一个转成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。

    例如将kitten一字转成sitting:

    1. sitten (k→s)
    2. sittin (e→i)
    3. sitting (→g)

    俄罗斯科学家Vladimir Levenshtein在1965年提出这个概念。

    问题:找出字符串的编辑距离,即把一个字符串s1最少经过多少步操作变成编程字符串s2,操作有三种,添加一个字符,删除一个字符,修改一个字符

    解析:

    首先定义这样一个函数——edit(i, j),它表示第一个字符串的长度为i的子串到第二个字符串的长度为j的子串的编辑距离。

    显然可以有如下动态规划公式:

    • if i == 0 且 j == 0,edit(i, j) = 0
    • if i == 0 且 j > 0, edit(i, j) = j
    • if i > 0 且j == 0, edit(i, j) = i
    • if i ≥ 1  且 j ≥ 1 ,edit(i, j) == min{ edit(i-1, j) + 1, edit(i, j-1) + 1, edit(i-1, j-1) + f(i, j) },当第一个字符串的第i个字符不等于第二个字符串的第j个字符时,f(i, j) = 1;否则,f(i, j) = 0。
      0 f a i l i n g
    0                
    s                
    a                
    i                
    l                
    n                
      0 f a i l i n g
    0 0 1 2 3 4 5 6 7
    s 1              
    a 2              
    i 3              
    l 4              
    n 5              

     计算edit(1, 1),edit(0, 1) + 1 == 2,edit(1, 0) + 1 == 2,edit(0, 0) + f(1, 1) == 0 + 1 == 1,min(edit(0, 1),edit(1, 0),edit(0, 0) + f(1, 1))==1,因此edit(1, 1) == 1。 依次类推:

      0 f a i l i n g
    0 0 1 2 3 4 5 6 7
    s 1 1 2 3 4 5 6 7
    a 2 2            
    i 3              
    l 4              
    n 5              

    edit(2, 1) + 1 == 3,edit(1, 2) + 1 == 3,edit(1, 1) + f(2, 2) == 1 + 0 == 1,其中s1[2] == 'a' 而 s2[1] == 'f'‘,两者不相同,所以交换相邻字符的操作不计入比较最小数中计算。以此计算,得出最后矩阵为:

      0 f a i l i n g
    0 0 1 2 3 4 5 6 7
    s 1 1 2 3 4 5 6 7
    a 2 2 1 2 3 4 5 6
    i 3 3 2 1 2 3 4 5
    l 4 4 3 2 1 2 3 4
    n 5 5 4 3 2 2 2 3

    程序(C++):注意二维数组动态分配和释放的方法!!

     1 #include <iostream>
     2 #include <string>
     3 
     4 using namespace std;
     5 
     6 int min(int a, int b)
     7 {
     8     return a < b ? a : b;
     9 }
    10 
    11 int edit(string str1, string str2)
    12 {
    13     int max1 = str1.size();
    14     int max2 = str2.size();
    15 
    16     int ptr[max1+1][max2+1];
    17     int ptr[0][0]=0;

    32 for(int i = 1 ;i < max1 + 1 ;i++) 33 { 34 for(int j = 1 ;j< max2 + 1; j++) 35 { 36 int d; 37 int temp = min(ptr[i-1][j] + 1, ptr[i][j-1] + 1); 38 if(str1[i-1] == str2[j-1]) 39 { 40 d = 0 ; 41 } 42 else 43 { 44 d = 1 ; 45 } 46 ptr[i][j] = min(temp, ptr[i-1][j-1] + d); 47 } 48 }

        for(int i = 0 ;i < max1 + 1 ;i++) 52 { 53 for(int j = 0; j< max2 + 1; j++) 54 { 55 cout << ptr[i][j] << " " ; 56 } 57 cout << endl; 58 }

      int dis = ptr[max1][max2]; 71  return dis; 72 } 73 74 int main() { 76 string str1 = "sailn"; 77 string str2 = "failing"; 78 79 int r = edit(str1, str2); 80 cout << "the dis is : " << r << endl; 81 82 return 0; 83 }
  • 相关阅读:
    vue 前端框架 (二) 表格增加搜索
    vue 前端框架
    数据结构-树的基本操作
    linux的串口驱动分析
    TTY驱动程序架构
    linux MTD系统解析(转)
    DM9000网卡的基本工作原理
    ok6410的LCD裸机范例
    ok6410的DMA裸机总结
    ok6410串口裸机总结
  • 原文地址:https://www.cnblogs.com/hellochennan/p/6608113.html
Copyright © 2011-2022 走看看