我正在尝试实施Rabin Karp算法的一点修改版本。我的想法是,如果我根据与每个字母相关的权重得到给定模式的哈希值,那么我不必担心字谜,所以我可以拿起字符串的一部分,计算其哈希值并且与传统方法的模式的哈希值进行比较,其中计算字符串和模式的两部分的哈希值,然后检查它们是否实际相似或者它可以是字谜。这是我的代码
string = "AABAACAADAABAABA"
pattern = "AABA"
#string = "gjdoopssdlksddsoopdfkjdfoops"
#pattern = "oops"
#get hash value of the pattern
def gethashp(pattern):
sum = 0
#I mutiply each letter of the pattern with a weight
#So for eg CAT will be C*1 + A*2 + T*3 and the resulting
#value wil be unique for the letter CAT and won't match if the
#letters are rearranged
for i in range(len(pattern)):
sum = sum + ord(pattern[i]) * (i + 1)
return sum % 101 #some prime number 101
def gethashst(string):
sum = 0
for i in range(len(string)):
sum = sum + ord(string[i]) * (i + 1)
return sum % 101
hashp = gethashp(pattern)
i = 0
def checkMatch(string,pattern,hashp):
global i
#check if we actually get first four strings(comes handy when you
#are nearing the end of the string)
if len(string[:len(pattern)]) == len(pattern):
#assign the substring to string2
string2 = string[:len(pattern)]
#get the hash value of the substring
hashst = gethashst(string2)
#if both the hashvalue matches
if hashst == hashp:
#print the index of the first character of the match
print("Pattern found at {}".format(i))
#delete the first character of the string
string = string[1:]
#increment the index
i += 1 #keep a count of the index
checkMatch(string,pattern,hashp)
else:
#if no match or end of string,return
return
checkMatch(string,pattern,hashp)
代码工作得很好。我的问题是这是一种有效的方法吗?可能存在逻辑可能失败的任何实例吗?我遇到的所有Rabin Karp算法都没有使用这个逻辑代替每一场比赛,它进一步逐字逐句检查,以确保它不是一个字谜。如果我这样做,那是不是错了?我的观点是,只要哈希值匹配,就会使用此代码,您无需逐个字符地逐一检查字符串,您可以继续查看下一个字符串。
答案 0 :(得分:1)
没有必要只有anagrams与模式的哈希值冲突。具有相同散列值的任何其他字符串也可能发生冲突。相同的哈希值可以充当骗子,因此需要逐个字符匹配。
例如在你的情况下,你正在采用mod 100.采用任何不同的101模式,然后通过Pigeonhole原则,其中至少有两个将具有相同的哈希值。如果您使用其中一个作为模式,那么如果您避免字符匹配,则其他字符串的存在会使您的输出出错。
此外,即使使用了您使用的哈希,两个字谜也可以具有相同的哈希值,这可以通过求解两个线性方程来获得。 例如,
DCE = 4*1 + 3*2 + 5*3 = 25
CED = 3*1 + 5*2 + 4*3 = 25