我正在尝试创建一个建议Mad Gab样式短语的算法。
输入是一组短语。我也有一组关键字,我想尽可能使用。目前,我的解决方案只是蛮力:
然而,我遇到的问题是:
我最熟悉PHP和MySQL。但是,如果能提供更好的解决方案,我会对另一项技术持开放态度。
我也对任何其他建议感兴趣。特别是使用metaphone()
的第二个参数来制作更难建议的方法。
答案 0 :(得分:6)
也许从短语bank上的音节分割算法开始。您甚至可以使用一个简单的资源来教孩子们划分音节来创建粗略的分隔符方法:
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
然后,您有一个单词bank的英语单词词典。有很多可用的开源词典可以放在MySQL表中。
从第一个音节开始,在字典中查找与soundex测试匹配的随机单词。如果找不到(这通常只能找到一个音节词),请添加附加音节并再次搜索。
示例:
“逻辑后果”
一个。音节分裂
“lo gi cal con sequ”“
B中。应用Vowel Sounds
“lah gee cahl con see quince”
℃。施加辅音声音
“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'));
我认为使用MySQL soundex比PHP soundex测试更容易,如果你想要一个大数据库的随机结果,你已经在字典表的字段中捕获了soundex值。
我的建议可能效率低下,但优化是一个不同的问题。
<强>更新强>
我并不是故意暗示我的解决方案只会产生一个音节词。我用一个音节作为例子,但如果你把两个音节放在一起,你就会得到多音节的匹配。事实上,你可能只是开始将所有音节一起干扰并在mysql中运行soundex。如果你找到答案,那很好。但是你可以滚动音节,直到你得到最长的匹配。然后你留下了短语的结尾,可以把它们放在一起并运行一个匹配。我认为这是其他贡献者下面解决方案的本质,但我认为你需要避免在没有空格的情况下将所有字母一起干扰。在英语中,你会丢失信息。想一个以“th”声开头的短语。如果将短语卡在一起,则会丢失所需的“声音”。 “Theremin”(乐器)的声音与“There,a man”不同。
答案 1 :(得分:3)
从Jonathan Barlow's solution采取不同的方法,我推荐使用O(n 2 )算法,该算法为您提供所寻找的属性,具有随机性,稳健性和可扩展性难度。这种算法的复杂性可以在恒定的时间内进一步改进,或者通过对搜索模态的优化来进一步改进,但是因为输入短语的大小保证很小,所以这并不是什么大问题。
构造all known words in the Oxford English Dictionary的哈希表和soundex()
值的单词列表地图。这最初听起来很棘手,直到你意识到实际上并没有那么多当前使用。假设一个体面的单向散列算法,这应该需要几兆字节,顶部。
将输入短语中的单词视为单个压缩字符串,不带任何单词标识,丢弃空格和所有标点符号。从这里开始,沿着所有角色长度行走,从一个长度开始,直到合并短语的全长减去一个。对于此walk产生的每个字符串,对OED执行哈希查找。当遇到字典中出现的单词时,将其单词和位置附加到内存中列表的末尾。
(此过程总是花费sum(n)
时间,这是定义的0.5n(n+1)
。所以,O(n 2 )它是。它的空间复杂度是最坏情况O(n 2 ),但在实践中,完全连接一套条款极不可能。)
现在出现了你的难度滑块。从生成的列表中,删除找到的条款的前N%,其中N是您的难度级别。这里的原则是,较小的单词对于某些人来说更容易进行词汇处理,而较长的单词则更难以发出和区分。
构造一个符合短语原始长度的数组(没有空格和标点符号)并随机播放您遇到的单词列表。现在,走一下洗牌清单。对于每个元素,验证数组中的所有插槽是否在该位置的原始位置都是空闲的。如果是,请保留单词及其位置,标记数组中使用的插槽。如果不是,则迭代到下一个单词,直到列表用完为止。*
从最终输出数组中,构造空间中未使用字符的分区列表,将每个字符包视为自己的短语。对于此列表,执行音节检测完全按照草绘here进行,将结果传递给metaphone()
,并将两个或多个音节组合在一起。然后,对于来自4的输出词典单词包,执行soundex()
,从单词的可比较soundex
值的映射列表中拉出一个随机单词。对于根据列表的支持映射只能soundex()
到自身的每个单词,执行分区和metaphone()
。最后,通过对位置进行排序并打印结果,将两个结果列表拼接在一起。
这是一个随机算法,我认为它是所有想要的属性,但在我看来它仍然很粗糙。
*额外学分:按字符或音节确定系统允许的重叠。这可以产生更大的接受输出短语范围和更高难度。