Chris@11
|
1
|
Chris@11
|
2 #include "EditDistance.h"
|
Chris@17
|
3 #include <algorithm>
|
Chris@11
|
4
|
Chris@13
|
5 #include <cstdlib> // abs
|
Chris@13
|
6
|
Chris@11
|
7 namespace ClassicalData
|
Chris@11
|
8 {
|
Chris@11
|
9
|
Chris@11
|
10 int
|
Chris@13
|
11 EditDistance::calculate(QString a, QString b, int threshold)
|
Chris@11
|
12 {
|
Chris@11
|
13 // Note: restricted Damerau-Levenshtein edit distance, or
|
Chris@11
|
14 // Levenshtein if NoTransposition
|
Chris@11
|
15
|
Chris@11
|
16 int al = a.length() + 1;
|
Chris@11
|
17 int bl = b.length() + 1;
|
Chris@11
|
18
|
Chris@13
|
19 if (threshold > 0 && abs(al - bl) > threshold) return threshold + 1;
|
Chris@13
|
20
|
Chris@11
|
21 int *currRow = (int *)alloca(sizeof(int) * bl);
|
Chris@11
|
22 int *prevRow = (int *)alloca(sizeof(int) * bl);
|
Chris@11
|
23 int *ppreRow = (int *)alloca(sizeof(int) * bl);
|
Chris@11
|
24 int *tmp = 0;
|
Chris@11
|
25
|
Chris@11
|
26 for (int i = 0; i < bl; ++i) {
|
Chris@28
|
27 prevRow[i] = i;
|
Chris@11
|
28 }
|
Chris@11
|
29
|
Chris@11
|
30 for (int j = 1; j < al; ++j) {
|
Chris@28
|
31 currRow[0] = j;
|
Chris@13
|
32 bool stillAcceptable = (threshold == 0);
|
Chris@11
|
33 for (int i = 1; i < bl; ++i) {
|
Chris@11
|
34 if (a[j-1] == b[i-1]) {
|
Chris@11
|
35 currRow[i] = prevRow[i-1];
|
Chris@11
|
36 } else {
|
Chris@11
|
37 int horizontal, vertical, diagonal;
|
Chris@28
|
38 horizontal = currRow[i-1] + 1;
|
Chris@28
|
39 diagonal = prevRow[i-1] + 1;
|
Chris@28
|
40 if (i+1 == bl) vertical = prevRow[i] + 1;
|
Chris@28
|
41 else vertical = prevRow[i] + 1;
|
Chris@11
|
42 currRow[i] =
|
Chris@11
|
43 std::min(horizontal, std::min(vertical, diagonal));
|
Chris@11
|
44 }
|
Chris@11
|
45 if (m_transpositionMode == RestrictedTransposition) {
|
Chris@11
|
46 if (i > 1 && j > 1 && a[i-1]==b[j-2] && a[i-2]==b[j-1]) {
|
Chris@28
|
47 currRow[i] = std::min(currRow[i], ppreRow[i-2] + 1);
|
Chris@11
|
48 }
|
Chris@11
|
49 }
|
Chris@13
|
50 if (threshold > 0 && currRow[i] <= threshold) {
|
Chris@13
|
51 stillAcceptable = true;
|
Chris@13
|
52 }
|
Chris@11
|
53 }
|
Chris@13
|
54 if (!stillAcceptable) return threshold + 1;
|
Chris@11
|
55 tmp = ppreRow;
|
Chris@11
|
56 ppreRow = prevRow;
|
Chris@11
|
57 prevRow = currRow;
|
Chris@11
|
58 currRow = tmp;
|
Chris@11
|
59 }
|
Chris@11
|
60
|
Chris@11
|
61 int result = prevRow[bl-1];
|
Chris@11
|
62 return result;
|
Chris@11
|
63 }
|
Chris@11
|
64
|
Chris@11
|
65 }
|
Chris@11
|
66
|