Вы можете сделать это, используя шаги, которые я обрисовал. Сначала я опишу алгоритм, за которым следует некоторый ( непроверенный и, возможно, неработающий ) Java-код.
Примечание: я буду использовать библиотеку apache commons-codec.
Алгоритм:
- Используйте регулярное выражение для представления вашего шаблона ввода.
- Из словаря "допустимых известных слов" отфильтруйте подмножество, соответствующее вашему регулярному выражению. Давайте назовем это согласованным подмножеством (MS)
- Используйте алгоритм двойного метафона для кодирования этих слов из MS.
- Примените фонетическую фильтрацию для сокращения MS в соответствии с вашими потребностями.
Чтобы проиллюстрировать, как работают шаги 3 и 4, я сначала покажу вам вывод алгоритма двойного метафона для пяти слов, которые вы предложили в качестве примеров: Cute, Cat, Cut, Caught, City
Код A (иллюстрирующий двойной метафон):
private static void doubleMetaphoneTest() {
org.apache.commons.codec.language.DoubleMetaphone dm = new DoubleMetaphone();
System.out.println("Cute\t"+dm.encode("Cute"));
System.out.println("Cat\t"+dm.encode("Cat"));
System.out.println("Cut\t"+dm.encode("Cut"));
System.out.println("Caught\t"+dm.encode("Caught"));
System.out.println("City\t"+dm.encode("City"));
}
Вывод кода A
Cute KT
Cat KT
Cut KT
Caught KFT
City ST
Теперь в своем вопросе вы заявили, что Сити не является правильным решением, потому что он начинается со звука "ESS". Double Metaphone поможет вам точно идентифицировать этот тип проблемы (хотя я уверен, что будут случаи, когда он не поможет). Теперь вы можете применить шаг 4 в алгоритме, используя этот принцип.
В следующем коде для шага 4 (примените некоторую фонетическую фильтрацию) я предполагаю, что вы уже знаете, что вам нужен только звук "K", а не звук "S".
Код B (прототип решения всего вопроса)
Примечание. Этот код предназначен для иллюстрации использования алгоритма DoubleMetaphone для ваших целей. Я не запускал код Регулярное выражение может быть нарушено или может быть очень неудачным, или мое использование Pattern Matcher может быть неправильным (сейчас 2 часа ночи). Если это не так, пожалуйста, улучшите / исправьте это.
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.codec.language.DoubleMetaphone;
public class GenerateWords {
/**
* Returns a set of words that conform to the input pattern
* @param inputPattern a regular expression
* @param lexicon a list of valid words
*/
public static List<String> fetchMatchingWordsFromLexicon(String inputPattern, List<String> lexicon){
/* E.g. for the case [C] * [T] * [N]
* the regex is:
* [Cc]+[aeiouyAEIOUY]+[Tt]+[aeiouyAEIOUY]+[Nn]+[aeiouyAEIOUY]+
*/
Pattern p = Pattern.compile(inputPattern);
List<String> result = new ArrayList<String>();
for(String aWord:lexicon){
Matcher m = p.matcher(aWord);
if(m.matches()){
result.add(aWord);
}
}
return result;
}
/**
* Returns the subset of the input list that "phonetically" begins with the character specified.
* E.g. The word 'cat' begins with 'K' and the word 'city' begins with 'S'
* @param prefix
* @param possibleWords
* @return
*/
public static List<String> filterWordsBeginningWithMetaphonePrefix(char prefix, List<String> possibleWords){
List<String> result = new ArrayList<String>();
DoubleMetaphone dm = new DoubleMetaphone();
for(String aWord:possibleWords){
String phoneticRepresentation = dm.encode(aWord); // this will always return in all caps
// check if the word begins with the prefix char of interest
if(phoneticRepresentation.indexOf(0)==Character.toUpperCase(prefix)){
result.add(aWord);
}
}
return result;
}
public static void main(String args[]){
// I have not implemented this method to read a text file etc.
List<String> lexicon = readLexiconFromFileIntoList();
String regex = "[Cc]+[aeiouyAEIOUY]+[Tt]+[aeiouyAEIOUY]+[Nn]+[aeiouyAEIOUY]+";
List<String> possibleWords = fetchMatchingWordsFromLexicon(regex,lexicon);
// your result
List<String> result = filterWordsBeginningWithMetaphonePrefix('C', possibleWords);
// print result or whatever
}
}