【问题标题】:Algorithm using soundex() or metaphone() to create Mad Gab style phrases使用 soundex() 或 metaphone() 创建 Mad Gab 风格短语的算法
【发布时间】:2012-04-04 08:19:47
【问题描述】:

我正在尝试创建一个算法来建议Mad Gab 风格的短语。

输入是一组短语。我还有一组关键字,我想尽可能使用它们。目前,我的解决方案只是蛮力:

  • 循环遍历短语(逐个字符)
    • 如果找到关键字
      • 存储关键字和分支(递归)
    • 增加字符数

但是,我遇到的问题是:

  • 复合关键字帐户,例如"catchs" 可以是 "catches"、"cat" + "cheeses"
  • 允许字面术语 - “the”、“and”、“one”、“two”、“three”。
  • 如何建议不是关键字的字词。即当找不到关键字或文字时,求助于系统字典之类的东西。
  • 跳过短语片段。现在它只是通过一次。但请考虑以下情况:短语以不匹配的内容开头,但后面的几个字符包含匹配项。

我最熟悉 PHP 和 MySQL。但是,如果它提供更好的解决方案,我对另一种技术持开放态度。

我也对任何其他建议感兴趣。特别是使用metaphone() 的第二个参数提出更难 建议的方法。

【问题讨论】:

  • 我看到的谜题都非常依赖于 1) 语音发音和 2) 对常用英语短语和名人姓名的了解。我不确定如果没有比您正在使用的更多知识,它们是否可以解决。
  • 拼音发音 = soundex(),对吧?我对在短语中使用名人不感兴趣。如前所述,我宁愿使用我的关键字。我的单词库中确实需要更多单词。因此,第三个要点。我的解决方案不完整。我非常愿意接受建议。
  • 非常有趣的问题。你可能要为我在工作中落后于我的最后期限负责。
  • @MrGomez,当然。提供答案。赏金对接下来的几天都有好处。
  • 我也在做一个,今晚或明天可以发布。

标签: php mysql soundex metaphone


【解决方案1】:

采取与Jonathan Barlow's solution 不同的策略,我推荐一种 O(n2) 算法,该算法在随机性、稳健性和可扩展难度方面为您提供您所寻求的属性。该算法的复杂性可以在恒定时间内或通过优化搜索方式进一步提高,但由于您的输入短语的大小保证很小,所以没什么大不了的。

  1. 构造all known words in the Oxford English Dictionary 的哈希表和soundex() 值的单词列表映射。这最初听起来很棘手,直到您意识到实际上并没有那么多当前使用的。假设一个不错的单向散列算法,这应该需要几兆字节。

  2. 将输入短语中的单词视为单个压缩字符串,没有任何单词标识,丢弃空格和所有标点符号。从这里开始,遍历所有字符长度的空间,从长度一开始,直到合并短语的全长减一。对于此遍历生成的每个字符串,针对 OED 执行哈希查找。当遇到字典中存在的单词时,将其单词和位置附加到内存中列表的末尾。

    (此传递将始终花费sum(n) 时间,根据定义0.5n(n+1)。所以,是 O(n2)。它的空间复杂度是最坏情况 O(n2),但在实践中,完全连接的项集是极不可能的.)

  3. 现在是您的难度滑块。从生成的列表中,删除找到的前 N% 的术语,其中 N 是您的难度级别。这里的原则是,较小的词更容易让人们在词汇上处理,而较长的词更难发音和区分。

  4. 构造一个符合短语原始长度的数组(不包括空格和标点符号),并将遇到的单词列表打乱。现在,走洗牌列表。对于每个元素,验证数组中的所有槽是否在其原始位置都可用于该单词。如果是,请保留单词及其位置,将插槽标记为数组中使用的位置。如果不是,则迭代到下一个单词,直到列表用完为止。*

  5. 从最终的输出数组中,构造空间中未使用字符的分区列表,将每个字符包视为自己的短语。对于这个列表,完全按照here 的草图执行音节检测,将结果传递给metaphone(),并有一定的几率将两个或多个音节组合在一起。然后,对于 4. 中的输出字典单词包,执行 soundex(),从单词的可比较 soundex 值的映射列表中拉出一个随机单词。根据列表的后备映射,对于每个只能soundex() 到自身的单词,执行分区和metaphone()。最后,通过按位置排序将两个结果列表拼接在一起并打印您的结果。

这是一个随机算法,我认为它具有所有所需的属性,但在我看来它仍然很粗糙。


 * 额外得分:按字符或音节确定系统允许的重叠。这可以使接受的输出短语范围更大,难度更高。

【讨论】:

  • 我非常喜欢这个。但我对第一步和第二步很好奇。如果散列算法本身不允许进行某种 soundex 比较,那么我不确定为什么在第 2 步之后,我们将不只是拥有短语中已经存在的单词的列表。因此,在“逻辑结果”经过一和二之后,如果没有 soundex,我们似乎会有 log、logic、logical、og、gi、calc、con、cons、on、seq、sequence、que。我不知道那个单词列表如何帮助我们达到形成语音短语的目标。但也许您打算对单词的 soundex 进行哈希处理?
  • @JonathanBarlow 就是这样。我们仍然需要具有可比较的soundex() 值的术语字典(我应该更清楚地说明这一点),但这将使我们能够从音节升级到完整的单词与英语短语绑定相似 .选项 B 只是使用您的方法,将其装订到 Markov model,这样我们就可以对这些条款进行有趣的绑定。哦,这真是一个有趣的问题。 :)
  • 今天我会审核你的答案。
  • @JasonMcCreary 一个明显的改进我忘了包括:对于每个只能soundex 对自己来说,执行分区和metaphone。我会用这个更新我的答案。
  • 从今晚摆弄我的 iPhone 开始,我发现了迄今为止最好的算法:只需让 Siri 安排约会。它认为我在谈论技术时会说最糟糕的
【解决方案2】:

也许从短语库上的音节划分算法开始。您甚至可以使用教孩子划分音节的简单资源来创建粗略的划分方法:

http://www.ewsdonline.org/education/components/scrapbook/default.php?sectiondetailid=7584

如果您想要一种更专业、更准确的方法,那么有博士学位。关于如何做的论文:

http://www.tug.org/docs/liang/

然后使用您自己滚动的内容或 metaphone() 将每个音节转换为语音表示。您可以使用解释元音发音规则的类似网站。这些只是概括。如果您自己滚动,您将处理元音与辅音分开。 Metaphone 只使用辅音,这很好,但不如你还考虑元音那么酷。

元音: http://www.eslgold.com/pronunciation/english_vowel_sounds.html 辅音: http://usefulenglish.ru/phonetics/english-consonant-sounds

然后,您的单词库中有一本英语单词词典。有许多可用的开源字典,您可以将它们粘贴到 MySQL 表中。

从第一个音节开始,在字典中查找与 soundex 测试匹配的随机单词。如果找不到(这通常只会找到一个音节词)添加额外的音节并再次搜索。

例子:

“逻辑结果”

A.音节分割

“逻辑后果”

B.应用元音

"lah gee cahl con see quince"

C.应用辅音

"lah jee kahl kon see quinse"

D. Soundtext 测试(一个音节 soundex - 显然太容易猜到,但它证明了这个概念)

“Law Gee Call Con Sea Quints”

Soundex strcmp 返回一个数字。因此,如果您愿意,您可以提前获取单词库中所有内容的 soundex 值。然后就可以快速运行strcmp了。

Soundex MySQL 比较的一个例子是:

选择 strcmp(soundex('lah'), soundex('law'));

如果您想从大型数据库中获取随机结果并且您已经在字典表的某个字段中捕获了 soundex 值,我认为使用 MySQL soundex 比 PHP soundex 测试更容易。

我的建议可能效率低下,但优化是另一个问题。

更新:

我并不是要暗示我的解决方案只会产生一个音节词。我以一个音节为例,但如果你把两个音节放在一起,你会得到多音节匹配。实际上,您可能只是从将所有音节组合在一起并在 mysql 中运行 soundex 开始。如果您找到答案,那就太好了。但是随后您可以滚动音节,直到获得最长的匹配。然后你就剩下短语的结尾了,你可以把它们放在一起进行匹配。我认为这是其他贡献者提供的以下解决方案的精髓,但我认为您需要避免将所有字母拼凑在一起而没有空格。在英语中,您会以这种方式丢失信息。想一个以“th”音开头的短语。如果你把这句话混在一起,你就会失去需要哪个“th”音。 “Theremin”(乐器)的“th”音与“There, a man”不同。

【讨论】:

  • +1,新颖的方法,出色的问题空间划分。我认为这个答案可以改进,但它勾勒出一个可用的解决方案来解决 OP 的问题。
  • 谢谢 - 我希望它是有帮助的。听起来是个有趣的项目。
  • 今天我会审核您的回答。乍一看,为什么是soundex() 而不是metaphone()
  • 嗨 Jason - 我建议使用 MySQL soundex,但没有原生 MySQL 变音。
  • 根据我的发现,metaphone()soundex() 更准确。但是,我想在一天结束时我可以互换使用。
猜你喜欢
  • 1970-01-01
  • 2012-07-19
  • 1970-01-01
  • 2016-09-19
  • 2011-03-14
  • 1970-01-01
  • 2023-01-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多