生成包含连续辅音的英语单词列表

时间:2010-02-18 22:21:40

标签: algorithm nlp

从这开始:

[G|C] * [T] *

编写一个生成此程序的程序:

Cat
Cut
Cute
City <-- NOTE: this one is wrong, because City has an "ESS" sound at the start.
Caught
...
Gate
Gotti
Gut
...
Kit
Kite
Kate
Kata
Katie

另一个例子,这个:

[C] * [T] * [N]

应该产生这个:

棉    小猫

我在哪里开始研究,因为我弄清楚如何编写一个执行此操作的程序/脚本?

6 个答案:

答案 0 :(得分:4)

您可以通过对包含单词的拼音版本的字典使用正则表达式来完成此操作。

这是Javascript中的一个例子:

     <html>
    <head>
        <title>Test</title>
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
        <script>

            $.get('cmudict0.3',function (data) {
                matches = data.match(/^(\S*)\s+K.*\sT.*\sN$/mg);
                $('body').html('<p>'+matches.join('<br/> ')+'</p>');
            })

        </script>
    </head>
    <body>
    </body>
</html>

您需要从http://icon.shef.ac.uk/Moby/mpron.tar.Z下载所有单词的列表,并将其(未压缩)放在与HTML文件相同的文件夹中。我只将[C] * [T] * [N]版本翻译成正则表达式,输出不是很好,但它会给你一个想法。以下是输出示例:

CALTON K AE1 L T AH0 N
CAMPTON K AE1 M P T AH0 N
CANTEEN K AE0 N T IY1 N
CANTIN K AA0 N T IY1 N
CANTLIN K AE1 N T L IH0 N
CANTLON K AE1 N T L AH0 N
...
COTTERMAN K AA1 T ER0 M AH0 N
COTTMAN K AA1 T M AH0 N
COTTON K AA1 T AH0 N
COTTON(2) K AO1 T AH0 N
COULSTON K AW1 L S T AH0 N
COUNTDOWN K AW1 N T D AW2 N
..
KITSON K IH1 T S AH0 N
KITTELSON K IH1 T IH0 L S AH0 N
KITTEN K IH1 T AH0 N
KITTERMAN K IH1 T ER0 M AH0 N
KITTLESON K IH1 T L IH0 S AH0 N
...

答案 1 :(得分:4)

你需要一个单词列表或字典,它使用像International Phonetic Alphabet这样的东西,或者其他一些标准的拼音方式。它需要有一个英文单词列表及其相应的拼音拼写。我不知道你会在哪里得到一个,因为我认为标准字典制作者不会发出那种信息。

答案 2 :(得分:2)

你想要moby发音。它是moby words项目的一部分。

您可以在此处找到解释和文档链接: http://en.wikipedia.org/wiki/Moby_Project

Moby发音是一个大约170k字及其语音发音的列表。

从那里开始构建程序应该是一个相对简单的过程。

答案 3 :(得分:1)

一种方法是将英语发音字典转换为有限状态机,然后使用正则表达式或简单的通配符机制进行搜索。您也可以通过生成语音转录的程序运行英语单词列表来自己编译这样的词典,例如:就像在这些网站上找到的那样:

找到一种从拼音到标准拼写的映射机制应该很容易。

答案 4 :(得分:1)

phoneme是“用于在话语之间形成有意义的对比的最小声音节段单位。”据我所知,这是基于发音的拼写校正系统的基础。尽管两个单词之间的编辑距离很大,但将报纸拼错为noospaypr可能会产生正确的修正,因为每个单词中的相应段(oo和ew,pa和pay,per和pr)可能会被转换为相同的音素。

不幸的是,几分钟我的谷歌搜索没有找到任何能够执行英语单词转换的库,但这就是我要开始的地方。

答案 5 :(得分:1)

您可以使用我概述的步骤进行一些操作。我将首先概述算法,然后是一些(未经测试且很可能已损坏的)java代码。

注意:我将使用apache commons-codec库。


算法:

  1. 使用正则表达式表示输入模式。
  2. 从“有效已知单词”的词典中过滤与您的正则表达式匹配的子集。我们称之为匹配子集(MS)
  3. 使用Double Metaphone算法对MS中的这些单词进行编码。
  4. 应用一些语音过滤来修剪MS以满足您的需求。

  5. 为了说明第3步和第4步的工作原理,我将首先向您展示Double Metaphone算法的输出,例如您建议的五个单词:Cute,Cat,Cut,Caught,City

    代码A(说明双重Metaphone):

    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算法的用途。我还没有运行代码。正则表达式可能会被破坏或者可能是一个非常蹩脚的正则表达式,或者我对Pattern Matcher的使用可能是错误的(现在是2AM)。如果有错,请改进/纠正。

    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
    
        }
    }