查找数组中具有大量相同字母的字符串对

时间:2016-11-07 08:01:05

标签: arrays string algorithm performance data-structures

假设我有一个不同长度的字符串数组 可以假设字符串没有重复字符 使用强力算法,我可以找到具有最多相同字母的字符串对(顺序无关紧要 - 例如," ABCDZFW"" FBZ"有3个相等的字母)在n平方的时间内 有没有更有效的方法呢?

尝试:我尝试使用trie数据结构来考虑解决方案,但这不会起作用,因为trie只会将具有相似前缀的字符串组合在一起。

1 个答案:

答案 0 :(得分:2)

  

我可以找到具有最多相同数量的字符串对   字母(顺序无关紧要 - 例如,“ABCDZFW”和“FBZ”都有   n平方时间内有3个相同的字母。

我认为你不能将字符串比较本身O(max(length(s1), length(s2)))O(n^2)循环一起检查所有对。但是,您可以在某种程度上优化字符串的比较。

正如你所提到的,字符串没有重复,我假设字符串根据你的输入只包含大写字母。所以,它变成每个字符串只能是26个字符。

对于每个字符串,我们可以使用位掩码。对于字符串的每个字符,我们可以设置相应的位1.例如:

ABCGH
11000111 (from LSB to MSB)

因此,n字符串有n位掩码。

方式#1

现在,您可以使用O(n^2)循环检查所有可能的字符串对,并通过ANDing两个相应的掩码比较字符串,并检查设置位数(汉明重量)。显然,这是对您的版本的改进,因为现在优化了字符串比较 - 只有两个32位整数之间的AND运算,这是一个O(1)操作。

例如对于任何两个字符串,比较将是:

ABCDG
ABCEF

X1 = mask(ABCDG) => 1001111
X2 = mask(ABCEF) => 0110111

X1 AND X2 => 0000111

hamming weight(0000111) => 3 // number of set bits
<#2>方式#2

现在,一个观察结果是相同类型的AND位是1.因此对于每个掩码,我们将尝试最大化两个字符串掩码的AND值的Hamming weight(设置位总数)作为字符串大多数匹配的字符具有相同的位1,并且这两个掩码的“与”将使这些位为1。

现在使用所有掩码构建Trie - 根据相应的位设置或不设置trie的每个节点将保持0或1。从MSB或LSB插入每个掩码。在将i掩码插入Trie(已经持有i - 1掩码)之前,我们将通过转到相同位的分支来查询以尝试最大化AND的汉明权重(以使最后的AND位变为1) )和也对着相对位的分支,因为在后面的级别中,您可能会在此分支中获得更多的设置位

关于这个Trie部分,为了获得精美的图片解释,你可以找到一个类似的线程here(这适用于XOR)。

在最坏的情况下,我们需要遍历许多trie分支以最大化汉明重量。在最坏的情况下,它将需要6 * 10^6次操作(在典型的机器中需要约1秒),而且我们还需要额外的空间来构建特里。但是说字符串的总数是10^5,那么对于O(n^2)算法,它会花费10^10次操作 - 所以trie方法仍然要好得多。

如果您遇到实施问题,请告诉我。不幸的是,只有当你是C / C ++或Java人时,我才能帮你解决代码问题。

感谢@JimMischel指出一个重大缺陷。我先稍微误解了这句话。