字符串编辑距离的几种实现
2016-03-23 20:04
423 查看
春暖花开,踏青时节,我看完了形式语言与自动机这一章这一章提到字符串编辑距离,于是动手实现了几个。编辑距离主要用于拼写纠错,貌似Google 2013的校招笔试题里就有这个。
通过插入删除或替换使得一个字符串变为另一个字符串的最小操作次数。
我这里取了花费固定为1,几个常量而已,随便改。
这种定义多了一个相邻字符交换位置的操作,实现起来稍有点复杂
常见的编辑距离定义
通过插入删除或替换使得一个字符串变为另一个字符串的最小操作次数。
用DP特简单
Java实现
我这里取了花费固定为1,几个常量而已,随便改。package com.hankcs; import java.util.Arrays; public class Main { public static void main(String[] args) { System.out.println(ed("sailn","failing")); System.out.println(ed("recoginze", "recognize")); System.out.println(ed("hack", "hankcs")); } public static int ed(String wrongWord, String rightWord) { final int m = wrongWord.length(); final int n = rightWord.length(); int[][] d = new int[m + 1][n + 1]; for (int j = 0; j <= n; ++j) { d[0][j] = j; } for (int i = 0; i <= m; ++i) { d[i][0] = i; } // for (int[] l : d) // { // System.out.println(Arrays.toString(l)); // } for (int i = 1; i <= m; ++i) { char ci = wrongWord.charAt(i - 1); for (int j = 1; j <= n; ++j) { char cj = rightWord.charAt(j - 1); if (ci == cj) { d[i][j] = d[i - 1][j - 1]; } else { // 等号右边的分别代表 将ci改成cj 错串加cj 错串删ci d[i][j] = Math.min(d[i - 1][j - 1] + 1, Math.min(d[i][j - 1] + 1, d[i - 1][j] + 1)); } } } // System.out.println(); // for (int[] l : d) // { // System.out.println(Arrays.toString(l)); // } return d[m][n]; } }
Du and Chang编辑距离
这种定义多了一个相邻字符交换位置的操作,实现起来稍有点复杂
一种常数时间花费较高但是很好理解的实现
package com.hankcs; import java.util.Arrays; public class MainPre { public static void main(String[] args) { System.out.println(ed("sailn","failing")); System.out.println(ed("recoginze", "recognize")); System.out.println(ed("hack", "hankcs")); } public static int ed(String wrongWord, String rightWord) { final int m = wrongWord.length(); final int n = rightWord.length(); int[][] d = new int[m + 1][n + 1]; for (int j = 0; j <= n; ++j) { d[0][j] = j; } for (int i = 0; i <= m; ++i) { d[i][0] = i; } // for (int[] l : d) // { // System.out.println(Arrays.toString(l)); // } for (int i = 1; i <= m; ++i) { char ci = wrongWord.charAt(i - 1); for (int j = 1; j <= n; ++j) { char cj = rightWord.charAt(j - 1); if (ci == cj) { d[i][j] = d[i - 1][j - 1]; } else if (i > 1 && j > 1 && ci == rightWord.charAt(j - 2) && cj == wrongWord.charAt(i - 2)) { // 交错相等 d[i][j] = 1 + Math.min(d[i - 2][j - 2], Math.min(d[i][j - 1], d[i - 1][j])); } else { // 等号右边的分别代表 将ci改成cj 错串加cj 错串删ci d[i][j] = Math.min(d[i - 1][j - 1] + 1, Math.min(d[i][j - 1] + 1, d[i - 1][j] + 1)); } } } // System.out.println(); // for (int[] l : d) // { // System.out.println(Arrays.toString(l)); // } return d[m][n]; } }
一种稍微饶了点弯弯并且自我感觉怪怪的实现
package com.hankcs; import java.util.Arrays; public class MainFinal { public static void main(String[] args) { System.out.println(ed("sailn","failing")); System.out.println(ed("recoginze", "recognize")); System.out.println(ed("hack", "hankcs")); } public static int ed(String wrongWord, String rightWord) { // 构造两个 NULL+字串,免得下标越界 wrongWord = '+' + wrongWord; rightWord = '+' + rightWord; final int m = wrongWord.length(); final int n = rightWord.length(); int[][] d = new int[m + 1][n + 1]; final int boarder = Math.max(m, n); for (int j = 2; j <= n; ++j) { d[0][j] = boarder; d[1][j] = j; } for (int i = 2; i <= m; ++i) { d[i][0] = boarder; d[i][1] = i; } // for (int[] l : d) // { // System.out.println(Arrays.toString(l)); // } for (int i = 2; i <= m; ++i) { char ci = wrongWord.charAt(i - 1); for (int j = 2; j <= n; ++j) { char cj = rightWord.charAt(j - 1); if (ci == cj) { d[i][j] = d[i - 1][j - 1]; } else if (ci == rightWord.charAt(j - 2) && cj == wrongWord.charAt(i - 2)) { d[i][j] = Math.min(d[i - 2][j - 2], Math.min(d[i - 1][j], d[i][j - 1])) + 1; } else { // 等号右边的分别代表 将ci改成cj 错串加cj 错串删ci d[i][j] = Math.min(d[i - 1][j - 1] + 1, Math.min(d[i][j - 1] + 1, d[i - 1][j] + 1)); } } } // System.out.println(); // for (int[] l : d) // { // System.out.println(Arrays.toString(l)); // } return d[m][n]; } }
相关文章推荐
- mysql数据库函数用法简析
- 贪心算法之物品分组
- 层次建树(优先插入左端),求二叉树的深度
- 简单的Python网络爬虫程序
- [LeetCode 265] Count Univalue Subtrees
- iOS-UILable总结
- 第三周练习 随机数函数应用于游戏——计算器
- ReactJS[未完待续]
- [置顶] 网络请求以及网络请求下载图片的工具类 android开发java工具类
- EMC开源产品rexray
- 对计算机组成原理的考研归纳(不断更新中)
- Android实现计时与倒计时(限时抢购)的几种方法
- grid刷新
- RobotFrameWork接口报文测试-----(一)简单demo的实现
- Hibernate
- 显示形状回归算法(ESR)代码介绍
- apache日志切割
- LeetCode OJ 217. Contains Duplicate
- podFile在pod 1.0.0.beta.4 版本下的语法参考
- [Elasticsearch] 邻近匹配 (三) - 性能,关联单词查询以及Shingles