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

    编辑距离(Edit Distance),又称Levenshtein距离,是指两个字串之间,由一个转成另一个所需的最少编辑操作次数。
    许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。
    例如将kitten一字转成sitting:
    sitten (k→s)
    sittin (e→i)
    sitting (→g)
    俄罗斯科学家Vladimir Levenshtein在1965年提出这个概念。应用:DNA分析、拼字检查、语音辨识、抄袭侦测、相似度计算。
     
    动态规划经常被用来作为这个问题的解决手段之一。
    整数 Levenshtein距离(字符串 str1[1..m], 字符串 str2[1..n])
    //声明变量, d[i , j]用于记录str1[0...i]与str2[0..j]的Levenshtein距离
    int d[0..m, 0..n]
    //初始化
    for i from 0 to m
      d[i, 0] := i //删除i个字符
    for j from 0 to n
      d[0, j] := j //插入j个字符
    //用动态规划方法计算Levenshtein距离
    for i from 1 to m
    {
      for j from 1 to n
      {
        //计算替换操作的代价,如果两个字符相同,则替换操作代价为0,否则为1
        if str1[i]== str2[j] then cost := 0
        else cost := 1
        //d[i,j]的Levenshtein距离,可以有
        d[i, j] := minimum{
        d[i-1, j] + 1, //在str1上i位置删除字符(或者在str2上j-1位置插入字符)
        d[i, j-1] + 1, //在str1上i-1位置插入字符(或者在str2上j位置删除字符)
        d[i-1, j-1] + cost // 替换操作
        }
      } 
    }
    //返回d[m, n]
    return d[m, n]
     
     

          这篇我们看看最长公共子序列的另一个版本,求字符串相似度(编辑距离),我也说过了,这是一个非常实用的算法,在DNA对比,网

    页聚类等方面都有用武之地。

    一:概念

         对于两个字符串A和B,通过基本的增删改将字符串A改成B,或者将B改成A,在改变的过程中我们使用的最少步骤称之为“编辑距离”。

    比如如下的字符串:我们通过种种操作,痉挛之后编辑距离为3,不知道你看出来了没有?

    二:解析

      可能大家觉得有点复杂,不好理解,我们试着把这个大问题拆分掉,将"字符串 vs 字符串“,分解成”字符 vs 字符串“,再分解

    成”字符 vs 字符“。

    <1> ”字符“vs”字符“

           这种情况是最简单的了,比如”A“与”B“的编辑距离很显然是1。

    <2> ”字符”vs"字符串"

           ”A“改成”AB“的编辑距离为1,“A”与“ABA”的编辑距离为2。

    <3>“字符串”vs“字符串”

          “ABA”和“BBA”的编辑距离为1,仔细发现我们可以得出如下结论,”ABA“是由23个子序列与”BBA“字符串求的的编辑距离集

    合中取出的最小编辑距离,也就是说在这种情况下我们出现了重复计算的问题,我在求子序列”AB“和”BBA"的编辑距离时,我是由

    子序列”A“和”BBA“与”B“和”BBA“之间的编辑距离中选出一个最小值,然而序列A和序列B早之前我已经计算过了,这种重复计算

    的问题有点像”斐波那契”,正好满足“动态规划”中的最优子结构和重叠子问题,所以我们决定采用动态规划来解决。

    三:公式

        跟“最长公共子序列”一样,我们采用一个二维数组来保存字符串X和Y当前的位置的最小编辑距离。

    现有两个序列X={x1,x2,x3,...xi},Y={y1,y2,y3,....,yi},

    设一个C[i,j]: 保存Xi与Yj的当前最小的LD。

    ①: 当 X= Yi 时,则C[i,j]=C[i-1,j-1];

    ②:当 X!= Y时, 则C[i,j]=Min{C[i-1,j-1],C[i-1,j],C[i,j-1]};

    最终我们的C[i,j]一直保存着最小的LD。

    四:代码

    复制代码
     1 using System;
     2 
     3 namespace ConsoleApplication2
     4 {
     5     public class Program
     6     {
     7         static int[,] martix;
     8 
     9         static string str1 = string.Empty;
    10 
    11         static string str2 = string.Empty;
    12 
    13         static void Main(string[] args)
    14         {
    15             while (true)
    16             {
    17                 str1 = Console.ReadLine();
    18 
    19                 str2 = Console.ReadLine();
    20 
    21                 martix = new int[str1.Length + 1, str2.Length + 1];
    22 
    23                 Console.WriteLine("字符串 {0} 和 {1} 的编辑距离为:{2}
    ", str1, str2, LD());
    24             }
    25         }
    26 
    27         /// <summary>
    28         /// 计算字符串的编辑距离
    29         /// </summary>
    30         /// <returns></returns>
    31         public static int LD()
    32         {
    33             //初始化边界值(忽略计算时的边界情况)
    34             for (int i = 0; i <= str1.Length; i++)
    35             {
    36                 martix[i, 0] = i;
    37             }
    38 
    39             for (int j = 0; j <= str2.Length; j++)
    40             {
    41                 martix[0, j] = j;
    42             }
    43 
    44             //矩阵的 X 坐标
    45             for (int i = 1; i <= str1.Length; i++)
    46             {
    47                 //矩阵的 Y 坐标
    48                 for (int j = 1; j <= str2.Length; j++)
    49                 {
    50                     //相等情况
    51                     if (str1[i - 1] == str2[j - 1])
    52                     {
    53                         martix[i, j] = martix[i - 1, j - 1];
    54                     }
    55                     else
    56                     {
    57                         //取“左前方”,“上方”,“左方“的最小值
    58                         var temp1 = Math.Min(martix[i - 1, j], martix[i, j - 1]);
    59 
    60                         //获取最小值
    61                         var min = Math.Min(temp1, martix[i - 1, j - 1]);
    62 
    63                         martix[i, j] = min + 1;
    64                     }
    65                 }
    66             }
    67 
    68             //返回字符串的编辑距离
    69             return martix[str1.Length, str2.Length];
    70         }
    71     }
    72 }
    复制代码

  • 相关阅读:
    Running ASP.NET Applications in Debian and Ubuntu using XSP and Mono
    .net extjs 封装
    ext direct spring
    install ubuntu tweak on ubuntu lts 10.04,this software is created by zhouding
    redis cookbook
    aptana eclipse plugin install on sts
    ubuntu open folderpath on terminal
    ubuntu install pae for the 32bit system 4g limited issue
    EXT Designer 正式版延长使用脚本
    用 Vagrant 快速建立開發環境
  • 原文地址:https://www.cnblogs.com/mmcmmc/p/3895538.html
Copyright © 2011-2022 走看看