先说点题外话,早上同学给我了一套卷子,让我做,他对象的机试题,第一题是求点队中的最小距离点对,没说数据量,那肯定直接暴力就行了(有给分点,正确输入给5分,什么什么给五分),或者分治算法(编程之美里的);第二题是替换字符串;第三题是求给出的四边形的面积,逼着认为这个不能用海伦公式,因为可能是凹四边形,需要向量公式。题目如此简单,这就是北邮,这种题目能考察出来水平么,哎,或许真是考研的学生水平都不高,只是会看书会考试而已。
昨晚吃饭,本科的张同学惊讶于我说的体重,找了个诊所,直接进去测,发现真的是70kg,本科时候我从来不到60kg。
一、问题来源
看云计算的书,提到微博去重,因为数据量巨大,需要先Hash再MapReduce,那么如何Hash把相似的微博尽可能放到同一个桶里呢?用哪个Hash呢,作者提出了局部敏感Hash算法,中间的距离度量函数可以使用编辑距离(Edit Distance),但是编辑距离右脚Levenshtein莱温斯坦距离,即LD,写到这,笔者突然想到,ED距离是不是就是编辑距离,原来我认为是欧几里得距离。哈哈,这真是“文章本天成,妙手偶得之”。
我查了资料发现编辑距离在NLP(神经语言程序学)中应用广泛。
二、问题分析
下面资料,来自北大,这真是人才的摇篮,我不知道我咋找到这个资料的,记得以前这类资料也都是pdf链接,现在依旧。而且笔者发现,他们的资料更加细致,可能出现的问题都做了标注,这些问题包括读者能想到的和不能想到的,很有启发性和警醒作用,为何说警醒,因为你突然发现自己的误解,那么就不会那么自满了;北大和我校的区别,就像高中老师和大学老师的区别。此偶之愚见也。
1.引入
源文:She is a star with the theatre company.
机器译文:她 是 与 剧院 公司 的 一 颗 星。
参考译文:她 是 剧团 的 明星。
2.算法分析
看完接下来的资料,我发现,Dijkstra算法从后往前推结果,编程却是从前往后,但是不理解,现在想来,这是必然的。因为d[i][j]=min{d[i-1][j-1]……},结果是d[m][n]不算出前面的怎么计算出d[m][n],从前往后是递推,从后往前类似递归,哈哈。
参考资料:http://ccl.pku.edu.cn/doubtfire/Course/Computational%20Linguistics/contents/Minimum%20Edit%20Distance.pdf
三、算法实现
1.Java版本
上面算法的变形实现,或者直接写个min(a,b,c)函数就是上面的算法实现了。
public class MinimumEditDistance {
public static int minEditDistance(String dest, String src) {
int[][] f = new int[dest.length()+1][src.length() + 1];
f[0][0] = 0;
for (int i = 1; i < dest.length() + 1; i ) {
f[i][0] = i;
}
for (int i = 1; i < src.length() + 1; i ) {
f[0][i] = i;
}
for (int i = 1; i < dest.length() + 1; i ) {
for (int j = 1; j < src.length() + 1; j ) {
// 替换的开销
int cost = 0;
if (dest.charAt(i - 1) != src.charAt(j - 1)) {
cost = 1;
}
int minCost;
if (f[i - 1][j] < f[i][j - 1]) {
minCost = f[i - 1][j] + 1;
} else {
minCost = f[i][j - 1] + 1;
}
if (minCost > f[i - 1][j - 1] + cost) {
minCost = f[i - 1][j - 1] + cost;
}
f[i][j] = minCost;
}
}
return f[dest.length()][src.length()];
}
public static void main(String[] args) {
System.out.println(minEditDistance("kindle", "ainelw"));
}
}
2.C/C++版本
#include
#include
char s1[1000],s2[1000];
int min(int a,int b,int c) {
int t = a < b ? a : b;
return t < c ? t : c;
}
void editDistance(int len1,int len2)
{
int** d=new int*[len1+1];
for(int k=0;k<=len1;k++)
d[k]=new int[len2+1];
int i,j;
for(i = 0;i <= len1;i++)
d[i][0] = i;
for(j = 0;j <= len2;j++)
d[0][j] = j;
for(i = 1;i <= len1;i++)
for(j = 1;j <= len2;j++)
{
int cost = s1[i] == s2[j] ? 0 : 1;
int deletion = d[i-1][j] + 1;
int insertion = d[i][j-1] + 1;
int substitution = d[i-1][j-1] + cost;
d[i][j] = min(deletion,insertion,substitution);
}
printf("%d\n",d[len1][len2]);
for(int k=0;i<=len1;k++)
delete[] d[k];
delete[] d;
}
int main()
{
while(scanf("%s %s",s1,s2) != EOF)
editDistance(strlen(s1),strlen(s2));
}