【发布时间】:2017-06-17 10:35:05
【问题描述】:
问题:查找所有遵循模式的单词(独立于用于定义模式的实际符号)。
几乎与本网站所做的相同:http://design215.com/toolbox/wordpattern.php
输入如下模式:ABCCDE
这会找到像“血腥”这样的词, “小猫”和“山谷”。上面的模式不会找到像这样的词 “茴香”或“嬉皮士”,因为这需要模式是 ABCCBE。
请注意:我需要该算法的一个版本,它可以找到像“fennel”或“hippie”这样的词,即使是 ABCDE 模式。
更复杂的是,可以在搜索模式的任何位置添加已知字符,例如:cBBX(其中 c 是已知字符)将产生cees、coof、cook、cool ...
到目前为止我所做的事情: 我找到了这个答案 (Pattern matching for strings independent from symbols) 几乎完美地解决了我的问题,但是如果我为需要比较的每个单词分配一个整数,我会遇到两个问题。
第一个是我可以使用的唯一数字的数量。例如,如果模式是 XYZABCDEFG,则等效的数字模式将是 1 2 3 4 5 6 7 8 9,然后呢? 10?考虑一下我会使用数字 0 来表示已知字符(例如,aBe --> 010 --> 10)。使用十六进制数字会使问题更进一步,但不会解决它。
第二个问题是模式的最大长度:Java 中的 Long 是 19 位长,我不需要限制我的模式(尽管我认为不存在一个包含 20 个不同字符的单词)。
为了解决这些问题,我可以将模式的每个数字存储在一个数组中,但是它变成了数组到数组的比较而不是整数比较,因此需要更多的时间来计算。
附带说明:根据所使用的算法,哪种数据结构最适合存储字典?我正在考虑使用散列映射,将每个单词转换为其等效的数字模式(假设没有已知字符)并将此数字用作散列(当然,会有很多冲突)。这样,搜索将首先需要匹配数字模式,然后扫描结果以找到所有在正确位置具有已知字符的单词(如果存在于原始搜索模式中)。
此外,字典不是静态的:可以添加和删除单词。
编辑:
这个答案 (https://stackoverflow.com/a/44604329/4452829) 效果很好,而且速度很快(在匹配模式之前测试相等的长度)。唯一的问题是我需要该算法的一个版本,即使使用 ABCCDE 模式也能找到像“fennel”或“hippie”这样的词。
我已经实现了一种检查已知字符的方法。
编辑 2:
好的,通过检查模式中的每个字符是否大于或等于当前单词中的相应字符(标准化为临时模式)我几乎完成了:它正确匹配搜索模式 ABCA 带有单词 ABBA 并且它正确地忽略了单词 ABAC。剩下的最后一个问题是,如果(例如)模式是 ABBA,它将匹配单词 ABAA,这是不正确的。
编辑 3:
嗯,不是很漂亮,但它似乎可以正常工作(我使用 Python,因为它的编码速度很快)。此外,搜索模式可以是任何符号序列,使用小写字母作为固定字符,其他所有字符作为通配符;也无需将每个单词转换为抽象模式。
def match(pattern, fixed_chars, word):
d = dict()
if len(pattern) != len(word):
return False
if check_fixed_char(word, fixed_chars) is False:
return False
for i in range(0, len(pattern)):
cp = pattern[i]
cw = word[i]
if cp in d:
if d[cp] != cw:
return False
else:
d[cp] = cw
if cp > cw:
return False
return True
【问题讨论】:
-
英文单词少于200,000个,看起来很多,其实不然。遍历它们并针对模式测试它们应该是您的第一次尝试。如果这太慢了,那么你有一个更具体的问题。
-
牛津英语词典有超过 600,000 个单词。无论如何,我会在接下来的几天内尝试按照您的建议进行操作。
-
另外,我想要一个足够快的算法来检查姓名列表(我找到了一个 Facebook 名字列表,它有超过 400 万个名字)。编辑:哇,那会很有趣(hackreports.com/2013/05/…)
标签: algorithm language-agnostic pattern-matching wildcard