您可以使用我概述的步骤来完成此操作。我将首先概述算法,然后是一些(未经测试且很可能已损坏)java代码。
注意:我将使用 apache commons-codec 库。
算法:
- 使用正则表达式来表示您的输入模式。
- 从“有效的已知单词”词典中过滤与您的正则表达式匹配的子集。我们称之为匹配子集 (MS)
- 使用 Double Metaphone 算法对来自 MS 的这些单词进行编码。
- 应用一些语音过滤来根据您的需要修剪 MS。
为了说明第 3 步和第 4 步的工作原理,我将首先向您展示 Double Metaphone 算法对您建议的五个单词的输出作为示例: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
现在在您的问题中,您已经说过 City 不是正确的解决方案,因为它以“ESS”声音开头。 Double Metaphone 将帮助您准确识别此类问题(尽管我确信在某些情况下它无法提供帮助)。现在您可以使用此原理在算法中应用第 4 步。
在下面的代码中,对于第 4 步(应用一些语音过滤),我假设您已经知道您只想要“K”音而不是“S”音。
代码 B(整个问题的原型解决方案)
注意:此代码旨在说明如何将 DoubleMetaphone 算法用于您的目的。我没有运行代码。正则表达式可能已损坏,或者可能是一个非常蹩脚的表达式,或者我对模式匹配器的使用可能是错误的(现在是凌晨 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
}
}