Я работаю над очень грубым первым наброском алгоритма, чтобы определить, насколько похожи 2 строки. Я также использую Расстояние Левенштейна для вычисления расстояния редактирования между строками.
В настоящее время я делю общее количество правок на размер большей строки. Если это значение ниже некоторого порога, в настоящее время случайно установленного на 25%, то они «достаточно похожи».
Однако это совершенно произвольно, и я не думаю, что это очень хороший способ вычислить сходство. Есть ли какое-то математическое уравнение или подход к вероятности / статистике, чтобы взять данные о расстоянии Левенштейна и использовать их, чтобы сказать: «Да, эти строки достаточно похожи, исходя из количества сделанных изменений и размера строк»?
Также , ключевым моментом здесь является то, что я использую произвольный порог, и я бы предпочел не делать этого. Как я могу вычислить этот порог вместо того, чтобы назначать его, чтобы я мог с уверенностью сказать, что 2 строки «достаточно похожи» ?
Я сравниваю строки, которые представляют трассировку стека Java. Причина, по которой я хочу это сделать, состоит в том, чтобы сгруппировать кучу заданных трассировок стека по сходству и использовать ее в качестве фильтра для сортировки «всякой всячины» :) Эта группировка важна по более высокоуровневой причине, которой я не могу поделиться публично.
На данный момент мой алгоритм (псевдокод) примерно такой:
/*
* The input lists represent the Strings I want to test for similarity. The
* Strings are split apart based on new lines / carriage returns because Java
* stack traces are not a giant one-line String, rather a multi-line String.
* So each element in the input lists is a "line" from its stack trace.
*/
calculate similarity (List list1, List list2) {
length1 = 0;
length2 = 0;
levenshteinDistance = 0;
iterator1 = list1.iterator();
iterator2 = list2.iterator();
while ( iterator1.hasNext() && iterator2.hasNext() ) {
// skip blank/empty lines because they are not interesting
str1 = iterator1.next(); length1 += str1.length();
str2 = iterator2.next(); length2 += str2.length();
levensteinDistance += getLevenshteinDistance(str1, str2);
}
// handle the rest of the lines from the iterator that has not terminated
difference = levenshteinDistance / Math.max(length1, length2);
return (difference < 0.25) ? true : false; // <- arbitrary threshold, yuck!
}