我想知道有没有人知道最长重复非重叠子字符串的(最优?)算法。
例如,在字符串
ABADZEDGBADEZ
中,最长的重复子字符串是“BAD”。顺便说一下,如果不存在这样的结果,算法应该提示发生了这样的事情。我猜这涉及到后缀树。
我相信这种算法肯定已经存在了。感谢您的帮助!
我想知道有没有人知道最长重复非重叠子字符串的(最优?)算法。
例如,在字符串
ABADZEDGBADEZ
中,最长的重复子字符串是“BAD”。顺便说一下,如果不存在这样的结果,算法应该提示发生了这样的事情。我猜这涉及到后缀树。
我相信这种算法肯定已经存在了。感谢您的帮助!
由于您将此应用于音乐,因此您可能并不需要完全匹配;从一个主题实例到另一个主题实例可能会存在预期差异。可以尝试查找基因序列分析算法 - 这种类型的内容有很多。尝试使用BLAST或其他对齐算法。
您还可以尝试使用WinEPI系列算法,以及这个特定结果集的各种前缀树实现(这些结果允许子字符串中存在间隙;例如,ABCID和AFBCD都包含ABCD)。如果您感兴趣,我实际上有一篇论文介绍了一个值得研究的算法;但我需要获得发布授权,请告诉我。
请注意,对于大型数据集来说,这实际上是非常复杂的主题(要高效地实现)。
来源:一两年的研究,涉及类似的(主题检测)主题。
一个简单的算法是这样的:
(正如其他回复所示,我在描述后缀数组。)
好的,这里有一个疯狂的想法。
创建一个函数,确定在O(n)(其中n是文本长度)中是否存在长度为k的重复子字符串。这可以通过使用滚动哈希(参见维基百科Rabin-Karp字符串匹配算法)在线性时间内生成所有n个哈希值,并使用散列表/BST(或映射或字典或您语言所称的任何内容)存储相应的子字符串位置来完成。在将当前哈希插入数据结构之前,我们检查是否以前见过它。如果以前见过,我们只需查找生成此哈希的索引,并查看相应的子字符串是否为非重叠匹配。
现在,我们可以在O(n)时间内找到k长度的子字符串,然后简单地运行二分搜索,以找到我们可以使用我们的函数找到非重叠子字符串匹配的最大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,我真的需要回去睡觉:)