我构建了一个函数,它根据Rabin-Karp算法以升序查找两个文本文件中最长的公共子字符串。 主要功能是“find_longest”,内部功能是:“make_hashtable”,“extend_fingerprints”和“has_match”。 我无法分析 has_match 的平均情况复杂性。
将n1,n2表示为text1,将text2和l表示为currunt“window”的大小。 fingers是子字符串的哈希表。
def has_match(text1,text2,fingers1,fingers2,l,r):
h = make_hashtable(fingers2,r)
for i in range(len(fingers1)):
for j in h[fingers1[i]]:
if text1[i:i+l] == text2[j:j+l]:
return text1[i:i+l]
return None
这是“make_hashtable”,这里我很确定复杂城市是O(n2-l + 1):
def make_hashtable(fingers, table_size):
hash_table=[[] for i in range(table_size)]
count=0
for f in fingers:
hash_table[f].append(count)
count+=1
return hash_table
这是“find_longest”,我添加了这个功能,尽管我不需要它来进行复杂性分析。
def find_longest(text1,text2,basis=2**8,r=2**17-1):
match = ''
l = 0 #initial "window" size
#fingerprints of "windows" of size 0 - all are 0
fingers1 = [0]*(len(text1)+1)
fingers2 = [0]*(len(text2)+1)
while match != None: #there was a common substring of len l
l += 1
extend_fingerprints(text1, fingers1, l, basis, r)
extend_fingerprints(text2, fingers2, l, basis, r)
match = has_match(text1,text2,fingers1,fingers2,l,r)
print(match)
return l-1
这是“extend_fingerprints”:
def extend_fingerprints(text, fingers, length, basis=2**8, r=2**17-1):
count=0
for f in fingers:
if count==len(fingers)-1:
fingers.pop(len(fingers)-1)
break
fingers[count]=(f*basis+ord(text[length-1+count]))%r
count+=1
我对这两个选项有疑问:
1的 O(n_2-l+1)+O(n_1-l+1)*O(l)
将r作为常数引用,而n1,n2非常大,因此在哈希表上会产生很多冲突(假设每个'单元'都有O(1)项,但总是有些“误报”)
2。O(n_2-l+1)+O(n_1-l+1)+O(l)
请参阅r作为适当的散列函数的最佳值,因此几乎没有冲突,这意味着如果两个文本在散列表中是相同的单元格,我们可以假设它们实际上是相同的文本?
我个人倾向于粗体陈述。 TNX。
答案 0 :(得分:1)
我认为答案是
O((n_2-l)+ l *(n_1-l))
。 (n_2-l)表示第二个文本的make_hashtable的复杂性。 l *(n_1-l)表示两个嵌套循环,它们遍历第一个文本的指纹中的每个项目,并执行1个比较操作(对于l长度切片),对于某些常量“m”,如果有一些项目哈希表中的索引相同。