我想知道是否有人知道最长重复非重叠子串的(最佳?)算法。
例如,在字符串
中ABADZEDGBADEZ
最长的反复出现是“不好”。顺便提一下,如果没有这样的结果,算法应该警告这样的事情已经发生。我猜这是涉及后缀树。
我确信这必须已存在于某个地方。谢谢你的帮助!
答案 0 :(得分:4)
由于您将此应用于音乐,您可能不会寻找100%匹配;从主题的一个实例到另一个实例将存在预期的差异。你可能会尝试查找基因序列分析算法 - 那里有很多这样的东西。尝试BLAST或其他对齐算法。
您还可以尝试WinEPI系列算法,以及此特定结果集的各种前缀树实现(这些结果允许子字符串中的间隙;例如,ABCID和AFBCD都包含ABCD)。我实际上有一篇关于算法的文章,如果你感兴趣的话可能值得一看;我需要获得发行授权,所以请告诉我。
请注意,对于大型数据集而言,这实际上是一个非常复杂的主题(为了有效)。
资料来源:关于可比(主题检测)主题的一两年研究。
答案 1 :(得分:4)
Suffix array是解决该问题的良好数据结构。
Jon Bentley在Programming Pearls中解决了这个问题。
答案 2 :(得分:1)
一个简单的算法就是这样做:
(正如刚发布的另一个回复所示,我在这里描述了一个后缀数组。)
答案 3 :(得分:0)
好的,这是一个疯狂的想法。
创建一个函数,确定在O(n)中是否存在长度为k的重复子字符串(其中n是文本的长度)。这可以通过使用滚动哈希(参见维基百科Rabin-Karp String Matching Algorithm)来生成线性时间内的所有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,我真的需要回去睡觉:))