Вот некоторый код, который я быстро создал, показывающий один из способов создания кандидатов и их «ранжирования».
Хитрость в том, что вы никогда не «проверяете» недопустимого кандидата.
Мне твое: "У меня заканчивается память, когда у меня есть расстояние редактирования 9" , кричит "комбинаторный взрыв".
Конечно, чтобы уклониться от комбинаторного взрыва, ты нене пытайтесь сгенерировать все слова, которые находятся на расстоянии от «9» от вашей работы с ошибками.Вы начинаете со слова с ошибкой и генерируете (довольно много) возможных кандидатов, но воздерживаетесь от создания слишком большого количества кандидатов, потому что тогда у вас возникнут проблемы.
(также обратите внимание, что это неНе имеет большого смысла вычислять до расстояния редактирования Левенштейна, равного 9, потому что технически любое слово, содержащее менее 10 букв, может быть преобразовано в любое другое слово, содержащее менее 10 букв в макс. 9 преобразованиях)
Вотпочему вы просто не можете проверить все слова на расстоянии до 9 без ошибки OutOfMemory или просто программы, которая никогда не завершается:
- , генерирующей все светодиоды до 1 дляслово "ptmizing" , при добавлении только одной буквы (от a до z) генерируется уже 9 * 26 вариантов (то есть 324 варианта) [есть 9 позиций, в которые можно вставить одну из 26 букв)
- генерация всех светодиодов до 2, добавление только одной буквы к тому, что, как мы знаем, уже генерирует 10 * 26 * 324 вариаций (60 840)
- геноценка всех светодиодов до 3 дает: 17 400 240 вариаций
И это только с учетом случая, когда мы добавляем одну, добавляем две или добавляем три буквы (мыне считая удаления, свопов и т. д.).И это слово с ошибкой, длина которого составляет всего девять символов.На «настоящих» словах он взрывается еще быстрее.
Конечно, вы могли бы стать «умными» и генерировать это таким образом, чтобы не было слишком много дураков и т. Д., Но суть осталась: взрывается комбинаторный взрыв быстро .
Во всяком случае ... Вот пример.Я просто передаю словарь допустимых слов (содержащий в данном случае только четыре слова) соответствующему методу, чтобы сохранить это сокращение.
Вы, очевидно, захотите заменить вызов на светодиод своим собственным светодиодом.реализация.
Двойной метафон - всего лишь пример: в реальной проверке орфографии слова, которые звучат «одинаково», несмотря на дальнейший светодиод, должны считаться «более правильными» и, следовательно, часто предлагать сначала.Например, «оптимизация» и «aupteemising» довольно далеки от светодиодной точки зрения, но используя двойной метафон, вы должны получить «оптимизацию» в качестве одного из первых предложений.
(заявление об отказе:следующее было проверено через несколько минут, оно не учитывает заглавные буквы, неанглийские слова и т. д .: это не настоящая проверка орфографии, просто пример)
@Test
public void spellCheck() {
final String src = "misspeled";
final Set<String> validWords = new HashSet<String>();
validWords.add("boing");
validWords.add("Yahoo!");
validWords.add("misspelled");
validWords.add("stackoverflow");
final List<String> candidates = findNonSortedCandidates( src, validWords );
final SortedMap<Integer,String> res = computeLevenhsteinEditDistanceForEveryCandidate(candidates, src);
for ( final Map.Entry<Integer,String> entry : res.entrySet() ) {
System.out.println( entry.getValue() + " @ LED: " + entry.getKey() );
}
}
private SortedMap<Integer, String> computeLevenhsteinEditDistanceForEveryCandidate(
final List<String> candidates,
final String mispelledWord
) {
final SortedMap<Integer, String> res = new TreeMap<Integer, String>();
for ( final String candidate : candidates ) {
res.put( dynamicProgrammingLED(candidate, mispelledWord), candidate );
}
return res;
}
private int dynamicProgrammingLED( final String candidate, final String misspelledWord ) {
return Levenhstein.getLevenshteinDistance(candidate,misspelledWord);
}
ЗдесьВы генерируете всех возможных кандидатов, используя несколько методов.Я реализовал только один такой метод (и быстро, поэтому он может быть поддельным, но это не главное;)
private List<String> findNonSortedCandidates( final String src, final Set<String> validWords ) {
final List<String> res = new ArrayList<String>();
res.addAll( allCombinationAddingOneLetter(src, validWords) );
// res.addAll( allCombinationRemovingOneLetter(src) );
// res.addAll( allCombinationInvertingLetters(src) );
return res;
}
private List<String> allCombinationAddingOneLetter( final String src, final Set<String> validWords ) {
final List<String> res = new ArrayList<String>();
for (char c = 'a'; c < 'z'; c++) {
for (int i = 0; i < src.length(); i++) {
final String candidate = src.substring(0, i) + c + src.substring(i, src.length());
if ( validWords.contains(candidate) ) {
res.add(candidate); // only adding candidates we know are valid words
}
}
if ( validWords.contains(src+c) ) {
res.add( src + c );
}
}
return res;
}