我想知道是否有人知道最长重复不重叠子字符串的(最佳?)算法。
例如,在字符串
阿巴泽德巴德兹
最长的重复将是“坏”。顺便说一句,如果没有这样的结果,算法应该提醒这样的事情已经发生。我的猜测是这涉及后缀树。
我确定这一定已经存在于某个地方。谢谢您的帮助!
我想知道是否有人知道最长重复不重叠子字符串的(最佳?)算法。
例如,在字符串
阿巴泽德巴德兹
最长的重复将是“坏”。顺便说一句,如果没有这样的结果,算法应该提醒这样的事情已经发生。我的猜测是这涉及后缀树。
我确定这一定已经存在于某个地方。谢谢您的帮助!
后缀数组是解决该问题的良好数据结构。
Jon Bentley在Programming Pearls中有一个解决这个问题的方法。
由于您将其应用于音乐,因此您可能不是在寻找 100% 的匹配;从一个主题实例到另一个主题实例之间会出现预期差异。您可以尝试查找基因序列分析算法——那里有很多各种各样的东西。尝试 BLAST 或其他对齐算法。
您还可以尝试 WinEPI 系列算法,以及此特定结果集的各种前缀树实现(这些结果允许子字符串中存在间隙;例如,ABCID 和 AFBCD 都包含 ABCD)。实际上,我有一篇关于算法的论文,如果您有兴趣,可能值得一看;我需要获得分销授权,所以请告诉我。
请注意,对于大型数据集,这实际上是一个非常复杂的主题(要有效地完成)。
资料来源:针对类似(主题检测)主题的一两年研究。
一个简单的算法是这样做的:
(正如刚刚发布的另一个回复所示,我在这里描述了一个后缀数组。)
好的,这是一个疯狂的想法。
创建一个函数,确定在 O(n) 中是否存在长度为 k 的重复子字符串(其中 n 是文本的长度)。这可以通过使用滚动散列(参见 wikipedia for Rabin-Karp String Matching Algorithm)在线性时间内生成所有 n 个散列并使用散列表/BST(或映射或字典或任何您的语言调用它)来存储对应的子串位置。在将当前哈希插入数据结构之前,我们检查我们之前是否见过它。如果以前见过,我们只需查找生成此哈希的索引,并查看相应的子字符串是否为非重叠匹配。
现在我们可以在 O(n) 时间内找到 ak 长度的子字符串,我们只需运行二进制搜索来找到最大的 k,我们可以使用我们的函数找到一个不重叠的子字符串匹配。
Python中的代码如下
A=23
MOD=10007 # use a random value in the real world
def hsh(text):
return sum([ord(c)*A**(len(text)-i-1) for i,c in enumerate(text)])%MOD
def k_substring(text, k):
substrings={}
cur=hsh(text[:k])
pwr=(A**(k-1))%MOD
substrings[cur]=[0]
for i in xrange(k,len(text)):
to_remove=(ord(text[i-k])*pwr)%MOD
to_add=ord(text[i])
cur-=to_remove
if cur<0:
cur+=MOD
cur=(cur*A)%MOD
cur=(cur+to_add)%MOD
if cur in substrings:
lst=substrings[cur]
for index in lst:
if index+k<=i-k+1 and text[index:index+k]==text[i-k+1:i+1]:
return index
lst.append(i-k+1)
else:
substrings[cur]=[i-k+1]
return -1
def longest_substring(text):
hi,lo=len(text),0
while hi>lo:
mid=(hi+lo+1)>>1
if k_substring(text,mid)==-1:
hi=mid-1
else:
lo=mid
index=k_substring(text,lo)
return text[index:index+lo]
(抱歉,如果不清楚。现在是早上 6:30,我真的需要回去睡觉了 :))