【问题标题】:Generate a list of English words containing consecutive consonant sounds生成包含连续辅音的英语单词列表
【发布时间】:2010-02-18 22:21:40
【问题描述】:

从这里开始:

[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]

应该产生这个:

棉 小猫

当我弄清楚如何编写执行此操作的程序/脚本时,我应该从哪里开始我的研究?

【问题讨论】:

  • 在您的版本之前阅读答案,用 ipa 符号替换字母并将这些与它们的拼写相关联。在任何情况下,正则表达式都是解决方案。您可以通过例如帮助基于字母的正则表达式。不匹配 "ci"ty 与 /k/ 并且有一些相当不错的东西。但是,为了完美起见,您将需要包括所有例外情况(即使对于尚不存在的单词),这对于像英语这样的语言来说是不可行的。 IMO 这个问题不是编程问题。你不能从无到有。
  • 使得像英语这样的语言不可行??咦!?这正是拼写检查器所做的!这怎么不是编程题?
  • 不,拼写检查器不会那样做。再读一遍。并了解您要做什么。
  • 好吧,尊敬的,也许拼写检查器不会按照的想法去做,但我发布了一个答案,它准确地展示了拼写检查器可以做什么,以及将它与我在我发布的原始问题(下面提供的屏幕截图)中提出的问题进行对比。感谢您的反馈。

标签: algorithm nlp


【解决方案1】:

您可以通过对包含单词拼音版本的字典使用正则表达式来做到这一点。

这是一个 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
...

【讨论】:

  • 正则表达式无法处理声音。
  • @danben:我已经更新了我的答案以反映对问题的正确理解。
【解决方案2】:

您需要使用International Phonetic Alphabet 之类的字词列表或字典,或使用其他一些标准的拼音方式来书写字词。它需要有一个英语单词列表及其相应的语音拼写。我不知道你会从哪里得到一本,因为我不认为标准的词典制作者只是分发那种信息。

【讨论】:

    【解决方案3】:

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

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

    Moby 发音是一个包含大约 170k 单词及其语音发音的列表。

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

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

      • 正则表达式无法处理声音。
      • 是的。编辑之前的原始帖子没有足够清楚地表明问题在于发音而不仅仅是拼写。
      • 真的吗?它在标题中说“辅音”,并提供了“小猫”的例子来匹配C*T*
      • 实际上,如果您将字典转换为包含音标的字典并用它构建相应的 fsa,正则表达式可以处理声音。
      • 很高兴您更改了答案以解决问题的症结所在。但是,您应该了解正则表达式/状态机无法自行匹配发音相似的单词。你所说的是将输入预处理成可以匹配的东西。
      【解决方案5】:

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

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

      【讨论】:

        【解决方案6】:

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

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


        算法:

        1. 使用正则表达式来表示您的输入模式。
        2. 从“有效的已知单词”词典中过滤与您的正则表达式匹配的子集。我们称之为匹配子集 (MS)
        3. 使用 Double Metaphone 算法对来自 MS 的这些单词进行编码。
        4. 应用一些语音过滤来根据您的需要修剪 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
        
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-10-12
          • 1970-01-01
          • 2015-06-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多