package at.lux.retrieval.metrics.impl;
/**
* Damerau-Levenstein Metric dynamic
* provides approximate string matching based on the Damerau-Levenstein Metric.
* @author Mathias Lux, mlux@know-center.at
* @version 1.0
*/
public class DLMetricDynamic {
private String str1, str2;
private int[][] f;
/**
* This method returns the distance between two Strings
* in Damerau-Levenstein Metric.<br>
* The returned value gives the number of basic transformations
* needed to convert str2 into str1.<br>
* Basic transformations (shown on the word KNOW):
* <ol>
* <li>add a letter (KNOWN)
* <li>remove a letter (KOW)
* <li>substitute a letter with another one (KNAW)
* <li>transpose 2 adjacent letters (NKOW)
* </ol>
*/
public int calculateDistance(String s1, String s2) {
str1 = s1;
str2 = s2;
f = new int[str1.length() + 1][str2.length() + 1];
f[0][0] = 0;
for (int i = 0; i < str1.length(); i++) f[i][0] = i;
for (int j = 0; j < str2.length(); j++) f[0][j] = j;
for (int i = 1; i < str1.length(); i++) {
for (int j = 1; j < str2.length(); j++) {
int left = Math.min(f[i - 1][j] + 1, f[i][j - 1] + 1);
int right;
if (i > 1 && j > 1)
right = Math.min(f[i - 1][j - 1] + distance(i, j), f[i - 2][j - 2] + distance(i - 1, j) + distance(i, j - 1) + 1);
else
right = f[i - 1][j - 1] + distance(i, j);
f[i][j] = Math.min(left, right);
}
}
return f[str1.length() - 1][str2.length() - 1];
}
private int distance(int i2, int j2) {
if (i2 > 0 && j2 > 0 && i2 <= str1.length() && j2 <= str2.length()) {
if (str1.charAt(i2 - 1) == str2.charAt(j2 - 1))
return 0;
else
return 1;
} else
return 0;
}
}