先說點題外話,早上同學給我了一套卷子,讓我做,他對象的機試題,第一題是求點隊中的最小距離點對,沒說數據量,那肯定直接暴力就行了(有給分點,正確輸入給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)); }