Неожиданные результаты от алгоритма Metaphone
Я использую фонетическое соответствие для разных слов в Java. Я использовал Soundex, но он слишком грубый. Я переключился на Метафон и понял, что это лучше. Однако, когда я строго проверил это. я обнаружил странное поведение. я должен был спросить, так ли работает метафон, или я использую его неправильно. В следующем примере это прекрасно работает:
Metaphone meta = new Metaphone();
if (meta.isMetaphoneEqual("cricket","criket")) System.out.prinlnt("Match 1");
if (meta.isMetaphoneEqual("cricket","criketgame")) System.out.prinlnt("Match 2");
Это будет печатать
Match 1
Mathc 2
Теперь "крикет" звучит как "крикет", но почему "крикет" и "игра в крикет" совпадают. Если кто-то объяснит это. это было бы очень полезно.
1 ответ
Ваше использование немного неверно. Быстрое исследование закодированных строк и максимальной длины кода по умолчанию показывает, что оно равно 4, что обрезает конец более длинной "игры в крикет":
System.out.println(meta.getMaxCodeLen());
System.out.println(meta.encode("cricket"));
System.out.println(meta.encode("criket"));
System.out.println(meta.encode("criketgame"));
Вывод (примечание "criketgame" усекается от "KRKTKM" до "KRKT", что соответствует "cricket"):
4 KRKT KRKT KRKT
Решение. Установите максимальную длину кода, соответствующую вашему приложению и ожидаемому вводу. Например:
meta.setMaxCodeLen(8);
System.out.println(meta.encode("cricket"));
System.out.println(meta.encode("criket"));
System.out.println(meta.encode("criketgame"));
Теперь выводы:
KRKT KRKT KRKTKM
И теперь ваш оригинальный тест дает ожидаемые результаты:
Metaphone meta = new Metaphone();
meta.setMaxCodeLen(8);
System.out.println(meta.isMetaphoneEqual("cricket","criket"));
System.out.println(meta.isMetaphoneEqual("cricket","criketgame"));
Печать:
правда ложный
Кроме того, вы также можете поэкспериментировать сDoubleMetaphone
, который является улучшенной версией алгоритма.
Кстати, обратите внимание на предостережение в документации по безопасности потоков:
Поле экземпляра
maxCodeLen
изменчив, но не является изменчивым, и доступы не синхронизированы. Если экземпляр класса совместно используется потоками, вызывающая сторона должна убедиться, что используется подходящая синхронизация для безопасной публикации значения между потоками, и не должна вызыватьsetMaxCodeLen(int)
после начальной настройки.