在这种情况下,您试图找到大文本文件中的所有单词,其文本也在文件中。
通过“反转”,我的意思是给出一个单词“abc”,看看文件中是否有“cba”。文本文件包含大约10,000,000个单词。单词的长度不超过1000。
我提出的想法是找到一个哈希来映射一个单词并将其恢复为同一个键。并重点关注关键。所以现在你可以线性检查以找到所有可能符合条件的单词。
问题是:“查找此哈希”。对此问题的任何其他棘手的解决方案都是受欢迎的。
如果我能找到一个哈希来将字符串映射到一个键,我可以使用外部排序对它们进行排序,并使字符串及其反转相邻。所以找到它们是微不足道的。
答案 0 :(得分:3)
最简单的哈希是:任何哈希(提供足够大的哈希空间)!
假设你的字符串是“foo”。它的反面是“oof”。在某些任意顺序(例如词典顺序)中,“foo”出现在“oof”之前。现在哈希首先按顺序出现的字符串。
所以而不是
hash = fancyHash(string);
你做了
std::string rstring(string.rbegin(), string.rend());
hash = (string < rstring) ? anyhash(string) : anyhash(rstring);
使用Linux工具的方式@HighPerformanceMark建议: (文本是包含您的单词的文件。它们可能在同一行,无关紧要)
rev text | tr "[:upper:]" "[:lower:]" | tr " " "\n" > rtext; rev rtext > rrtext; comm -12 <(sort -u rrtext) <(sort -u rtext);
说明:
rev
会撤消文件,因此rev text
会反转
tr "[:upper:]" "[:lower:]"
将所有内容转换为小写(可选。如果“Foo”不计为“oOf”的反转,请不要这样做)
tr " " "\n"
为每个单词提供单独的文件
在此之后,文件rtext
在不同的行上包含小写(可选)字。此文件中的每个单词都是文件text
的反转单词。
rev rtext > rrtext
再次反转一个,以便将小写的内容添加到原始内容中,并将不同行上的每个单词分开。
comm -12 <(sort -u rrtext) <(sort -u rtext)
。作为comm
的输入,我们提供了两个文本文件,我们先排序并复制(-u
)。选项-12
会抑制对第一个输入(rrtext
)或第二个输入(rtext
)唯一的所有单词。因此,此命令的每个输出都存在于两个文件中。
答案 1 :(得分:2)
因此,如果您将所有单词读入map
(或unordered_map
,通过哈希表实现),那么您可以浏览单词列表,然后查找(使用map.find(the_word.reverse())
- 如果用有效的单词返回,则列表中有单词。否则,单词没有相反的变体。
答案 2 :(得分:2)
阅读输入列表。对于每个单词,将两个写入输出列表,单词本身及其反转。对输出列表进行排序。反转出现在原始列表中的单词将在排序的输出列表中出现两次(在连续的位置),其反转不在原始列表中的单词将只出现一次。
我认为您可以使用标准Linux文件处理实用程序和一些管道在一行中完成此操作。例如
rev wordlist.txt > revlist.txt && cat wordlist.txt revlist.txt | sort | uniq -c
考虑到现代现成排序程序的速度,我怀疑这可能会比具有更低(渐近)复杂度的更复杂算法更胜一筹。但这只是猜测。
答案 3 :(得分:2)
获取所有单词的列表(在程序中或通过gnu shell工具), 得到所有反转词的排序列表(相同) 交叉列表(也称为联接作为gnu工具)
而不是列表,程序当然也可以使用集合表示,尤其是散列集(unordered_set)。但是,如果文件非常大,则可能会遇到内存问题,而sort&amp; join可以基于磁盘工作。此外,hashsets不太适合计算交集
关于你的解决方案: 如果同一个单词包含两次,它也将具有相同的散列并且看起来存在反转
答案 4 :(得分:1)
如果“cat”和“cat”出现在没有“tac”的同一文件中,这个解决方案不会遇到问题。
Create a HashSet to hold strings.
For each word w in the file
Reverse w (call it revW)
If HashSet contains revW
Both w and revW appear in the file, add it to our results list.
Regardless, Add w into the HashSet (we might see another revW later on)
在算法上,你只读了一次文件,你翻转每一个单词一次,你在每个单词的反向查找哈希集,然后将每个单词添加到哈希集中。
所以这个算法是线性复杂度,假设HashSet / HashFunction提供恒定的时间查找/插入。
(可选择对HashSet中的每个单词进行计数,以跟踪该单词出现的次数)。
所以,所有的单词都会向前移动,但你只能将它们反转。