给定源字符串s
和n
等长字符串,我需要找到一个快速算法来返回最多k
个与源字符串不同的字符串每个相应位置s
。
这样做的快速算法是什么?
PS:我必须声称这是一个academic
问题。如果可能,我想找到最有效的算法。
此外,我错过了一条非常重要的信息。 n
等长字符串形成一个字典,将查询许多源字符串s
。似乎有某种预处理步骤可以提高效率。
答案 0 :(得分:2)
我的直觉就是迭代每个字符串n
,维护一个与s
不同的字符数的计数器,但我并没有声称它是最有效的解决方案。然而,这将是O(n)所以,除非这是一个已知的性能问题或学术问题,否则我会选择。
答案 1 :(得分:2)
Sedgewick在他的书“算法”中写道Ternary Search Tree允许“to locate all words within a given Hamming distance of a query word”。 Article in Dr. Dobb's
答案 2 :(得分:1)
鉴于字符串是固定长度,您可以计算两个字符串之间的Hamming distance来确定相似性;这是字符串长度的O(n)。因此,最糟糕的情况是您的算法为O(nm),用于将字符串与m个字进行比较。
作为替代方案,快速解决方案也是一种记忆困难,就是将字典预处理成地图; keys是一个元组(p,c),其中p是字符串中的位置,c是该位置字符串中的字符,值是在该位置有字符的字符串(所以“the”将出现在地图中{(0,'t'),“the”},{(1,'h'),“the”},{(2,'e'),“the”})。要查询地图,请遍历查询字符串的字符并使用检索到的字符串构造结果映射; keys是字符串,values是从主映射中检索字符串的次数(因此使用查询字符串“the”,键“thx”的值为2,键“tee”将具有价值1)。最后,遍历结果映射并丢弃其值小于K的字符串。
您可以通过在结果映射完成时丢弃不可能等于K的键来节省内存。例如,如果K为5且N为8,那么当您到达查询字符串的第4到第8个字符时,您可以丢弃任何尚未包含在结果映射中的字符串,因为它们不可能具有5匹配字符。或者,当您完成查询字符串的第6个字符后,您可以遍历结果映射并删除值小于3的所有键。
如果需要,您可以将主要预先计算的地图卸载到NoSql键值数据库或沿着这些行的某些内容,以便保存在主内存中(并且还可以使您不必在每次程序时预先计算字典重新启动)。
不是将元组(p,c)存储为主映射中的键,而是将位置和字符连接成一个字符串(所以(5,'t')变为“5t”,并且(12, 'x')变为“12x”。
答案 3 :(得分:0)
在不知道每个输入字符串中匹配字符的位置的情况下,对于特定字符串,无论您检查它们的顺序如何,都可能需要检查每个字符。因此,只需迭代每个字符串字符, - 字符并保持不匹配总数的总和。如果i
是到目前为止的不匹配数,则在false
时返回i == k
,并在字符串中剩余少于true
个未检查字符时返回k-i
。< / p>
请注意,根据字符串的长度以及允许的不匹配数量,迭代整个字符串而不是执行这些检查可能会更快,或者可能仅在每个字符后执行它们。玩弄它,看看你如何获得最快的表现。
答案 4 :(得分:0)
我的方法,如果我们大声思考:P我没有通过每个n
字符串看不到这样做的方法,但我很高兴得到纠正。在此过程中,它将以预处理开始,以保存第二组n
字符串,以便字符按升序排列。
比较的第一部分是检查每个n
字符串,一次对n'
中的每个字符s
说s'
。{/ {} p>
如果s'
小于n'
则不等于并移至下一个s'
。如果n'
小于s'
,请转到下一个n'
。否则记录匹配的字符。重复此操作,直到找到k
未命中匹配项或找到其他匹配项,并相应地标记n
。
为了进一步考虑,可以对n
中的每个相邻字符串进行添加的预处理,以查看不同字符的总数。然后可以在将字符串n
与s
进行比较时使用,如果这些与相邻的n
之间存在足够的差异,则可能不需要对其进行比较吗?