字符串编辑距离的几种实现

春暖花开,踏青时节,我看完了形式语言与自动机这一章这一章提到字符串编辑距离,于是动手实现了几个。编辑距离主要用于拼写纠错,貌似Google 2013的校招笔试题里就有这个。

常见的编辑距离定义

通过插入删除或替换使得一个字符串变为另一个字符串的最小操作次数。

用DP特简单

Java实现

我这里取了花费固定为1,几个常量而已,随便改。


  
  
  1. package com.hankcs;
  2.  
  3. import java.util.Arrays;
  4.  
  5. public class Main
  6. {
  7.  
  8.     public static void main(String[] args)
  9.     {
  10.         System.out.println(ed("sailn","failing"));
  11.         System.out.println(ed("recoginze", "recognize"));
  12.         System.out.println(ed("hack", "hankcs"));
  13.     }
  14.  
  15.     public static int ed(String wrongWord, String rightWord)
  16.     {
  17.         final int m = wrongWord.length();
  18.         final int n = rightWord.length();
  19.  
  20.         int[][] d = new int[+ 1][+ 1];
  21.         for (int j = 0; j <= n; ++j)
  22.         {
  23.             d[0][j] = j;
  24.         }
  25.         for (int i = 0; i <= m; ++i)
  26.         {
  27.             d[i][0] = i;
  28.         }
  29.  
  30. //        for (int[] l : d)
  31. //        {
  32. //            System.out.println(Arrays.toString(l));
  33. //        }
  34.  
  35.         for (int i = 1; i <= m; ++i)
  36.         {
  37.             char ci = wrongWord.charAt(- 1);
  38.             for (int j = 1; j <= n; ++j)
  39.             {
  40.                 char cj = rightWord.charAt(- 1);
  41.                 if (ci == cj)
  42.                 {
  43.                     d[i][j] = d[- 1][- 1];
  44.                 }
  45.                 else
  46.                 {
  47.                     // 等号右边的分别代表 将ci改成cj                   错串加cj         错串删ci
  48.                     d[i][j] = Math.min(d[- 1][- 1] + 1, Math.min(d[i][- 1] + 1, d[- 1][j] + 1));
  49.                 }
  50.             }
  51.         }
  52.  
  53. //        System.out.println();
  54. //        for (int[] l : d)
  55. //        {
  56. //            System.out.println(Arrays.toString(l));
  57. //        }
  58.  
  59.         return d[m][n];
  60.     }
  61. }

Du and Chang编辑距离

这种定义多了一个相邻字符交换位置的操作,实现起来稍有点复杂

一种常数时间花费较高但是很好理解的实现


  
  
  1. package com.hankcs;
  2.  
  3. import java.util.Arrays;
  4.  
  5. public class MainPre
  6. {
  7.  
  8.     public static void main(String[] args)
  9.     {
  10.         System.out.println(ed("sailn","failing"));
  11.         System.out.println(ed("recoginze", "recognize"));
  12.         System.out.println(ed("hack", "hankcs"));
  13.     }
  14.  
  15.     public static int ed(String wrongWord, String rightWord)
  16.     {
  17.         final int m = wrongWord.length();
  18.         final int n = rightWord.length();
  19.  
  20.         int[][] d = new int[+ 1][+ 1];
  21.         for (int j = 0; j <= n; ++j)
  22.         {
  23.             d[0][j] = j;
  24.         }
  25.         for (int i = 0; i <= m; ++i)
  26.         {
  27.             d[i][0] = i;
  28.         }
  29.  
  30. //        for (int[] l : d)
  31. //        {
  32. //            System.out.println(Arrays.toString(l));
  33. //        }
  34.  
  35.         for (int i = 1; i <= m; ++i)
  36.         {
  37.             char ci = wrongWord.charAt(- 1);
  38.             for (int j = 1; j <= n; ++j)
  39.             {
  40.                 char cj = rightWord.charAt(- 1);
  41.                 if (ci == cj)
  42.                 {
  43.                     d[i][j] = d[- 1][- 1];
  44.                 }
  45.                 else if (> 1 && j > 1 && ci == rightWord.charAt(- 2) && cj == wrongWord.charAt(- 2))
  46.                 {
  47.                     // 交错相等
  48.                     d[i][j] = 1 + Math.min(d[- 2][- 2], Math.min(d[i][- 1], d[- 1][j]));
  49.                 }
  50.                 else
  51.                 {
  52.                     // 等号右边的分别代表 将ci改成cj                   错串加cj         错串删ci
  53.                     d[i][j] = Math.min(d[- 1][- 1] + 1, Math.min(d[i][- 1] + 1, d[- 1][j] + 1));
  54.                 }
  55.             }
  56.         }
  57.  
  58. //        System.out.println();
  59. //        for (int[] l : d)
  60. //        {
  61. //            System.out.println(Arrays.toString(l));
  62. //        }
  63.  
  64.         return d[m][n];
  65.     }
  66. }

一种稍微饶了点弯弯并且自我感觉怪怪的实现


  
  
  1. package com.hankcs;
  2.  
  3. import java.util.Arrays;
  4.  
  5. public class MainFinal
  6. {
  7.  
  8.     public static void main(String[] args)
  9.     {
  10.         System.out.println(ed("sailn","failing"));
  11.         System.out.println(ed("recoginze", "recognize"));
  12.         System.out.println(ed("hack", "hankcs"));
  13.     }
  14.  
  15.     public static int ed(String wrongWord, String rightWord)
  16.     {
  17.         // 构造两个 NULL+字串,免得下标越界
  18.         wrongWord = '+' + wrongWord;
  19.         rightWord = '+' + rightWord;
  20.         final int m = wrongWord.length();
  21.         final int n = rightWord.length();
  22.  
  23.         int[][] d = new int[+ 1][+ 1];
  24.         final int boarder = Math.max(m, n);
  25.         for (int j = 2; j <= n; ++j)
  26.         {
  27.             d[0][j] = boarder;
  28.             d[1][j] = j;
  29.         }
  30.         for (int i = 2; i <= m; ++i)
  31.         {
  32.             d[i][0] = boarder;
  33.             d[i][1] = i;
  34.         }
  35.  
  36. //        for (int[] l : d)
  37. //        {
  38. //            System.out.println(Arrays.toString(l));
  39. //        }
  40.  
  41.         for (int i = 2; i <= m; ++i)
  42.         {
  43.             char ci = wrongWord.charAt(- 1);
  44.             for (int j = 2; j <= n; ++j)
  45.             {
  46.                 char cj = rightWord.charAt(- 1);
  47.                 if (ci == cj)
  48.                 {
  49.                     d[i][j] = d[- 1][- 1];
  50.                 }
  51.                 else if (ci == rightWord.charAt(- 2) && cj == wrongWord.charAt(- 2))
  52.                 {
  53.                     d[i][j] = Math.min(d[- 2][- 2], Math.min(d[- 1][j], d[i][- 1])) + 1;
  54.                 }
  55.                 else
  56.                 {
  57.                     // 等号右边的分别代表 将ci改成cj                   错串加cj         错串删ci
  58.                     d[i][j] = Math.min(d[- 1][- 1] + 1, Math.min(d[i][- 1] + 1, d[- 1][j] + 1));
  59.                 }
  60.             }
  61.         }
  62.  
  63. //        System.out.println();
  64. //        for (int[] l : d)
  65. //        {
  66. //            System.out.println(Arrays.toString(l));
  67. //        }
  68.  
  69.         return d[m][n];
  70.     }
  71. }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值