首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python: Rabin-Karp算法散列

Python: Rabin-Karp算法散列
EN

Stack Overflow用户
提问于 2014-03-06 14:37:15
回答 2查看 13.3K关注 0票数 6

为了好玩,我正在实现Rabin-Karp算法。我偶然发现了这个伪代码:

代码语言:javascript
复制
    RABIN -KARP -MATCHER (T, P, d, q)
    1 n = T.length
    2 m = P.length
    3 h = d^(m-1) mod q
    4 p=0
    5 t= 0
    6 for i = 1 to m
    / preprocessing
    /
    7 p = (dp + P [i]) mod q
    8 t = (dt + T [i]) mod q
    9 for s = 0 to n-m
    / matching
    /
    10     if p == t
    11         if P [1... m] == T [s + 1...s + m]
    12             print “Pattern occurs with shift” s
    13     if s < n-m
    14         t  = (d(t-T[s + 1]h) + T [s + m + 1]) mod q

我在Python 2.7中实现了如下代码:

代码语言:javascript
复制
def Rabin_Karp_Matcher(text, pattern, d, q):
    n = len(text)
    m = len(pattern)
    h = pow(d,m-1)%q
    p = 0
    t =0
    result = []
    for i in range(m): # preprocessing
        p = (d*p+ord(pattern[i]))%q
        t = (d*t+ord(text[i]))%q
    for s in range(n-m):
        if p == t: # check character by character
            match = True
            for i in range(m):
                if pattern[i] != text[s+i]:
                    match = False
                    break
            if match:
                result = result + [s]
        if s < n-m:
                t = (d*(t-ord(text[s+1])*h)+ord(text[s+m]))%q #index out of bounds here
    return result

其中,result是包含模式文本中的索引的列表。

我的代码在3141592653589793中找不到26,我怀疑这与伪代码的第14行定义的哈希代码有关。有人能帮个忙吗。

我传入了以下参数:

P= "26“T= "3141592653589793”d=257q= 11

P和T必须是字符串/字符数组

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-03-06 16:28:14

以下是您的代码的工作版本:

代码语言:javascript
复制
def Rabin_Karp_Matcher(text, pattern, d, q):
    n = len(text)
    m = len(pattern)
    h = pow(d,m-1)%q
    p = 0
    t = 0
    result = []
    for i in range(m): # preprocessing
        p = (d*p+ord(pattern[i]))%q
        t = (d*t+ord(text[i]))%q
    for s in range(n-m+1): # note the +1
        if p == t: # check character by character
            match = True
            for i in range(m):
                if pattern[i] != text[s+i]:
                    match = False
                    break
            if match:
                result = result + [s]
        if s < n-m:
            t = (t-h*ord(text[s]))%q # remove letter s
            t = (t*d+ord(text[s+m]))%q # add letter s+m
            t = (t+q)%q # make sure that t >= 0
    return result
print (Rabin_Karp_Matcher ("3141592653589793", "26", 257, 11))
print (Rabin_Karp_Matcher ("xxxxx", "xx", 40999999, 999999937))

输出为:

代码语言:javascript
复制
[6]
[0, 1, 2, 3]

在第一步中,您将检查text[0..m] == pattern。在第二步中,您需要检查text[1..m+1] == pattern。因此,您从散列中删除了text[0] (此时它被乘以预先计算的h):t = (t-h*ord(text[s]))%q。然后,向其添加text[m]t = (t*d+ord(text[s+m]))%q。在下一步中,删除text[1]并添加text[m+1],依此类推。之所以有t = (t+q)%q行,是因为模数为q的负数会产生范围(-q; 0]中的余数,我们希望它在范围[0; q)中。

请注意,您希望检查n-m+1子字符串的总数,而不是n-m,因此正确的循环是for s in range(n-m+1)。由第二个示例检查(在“xxxxx”中找到"xx“)。

同样值得注意的是:

如果m很大,

  1. h = pow(d,m-1)%q可能会太慢。在最坏的情况下,在每个multiplications.
  2. This算法仍然是O(nm)之后,最好取模q的结果。使用text="a"*100000pattern="a"*50000,它将找到50001个文本的子串与模式匹配的位置,并逐个字符地检查它们。如果您希望您的代码在这种极端情况下能够快速工作,您应该跳过逐个字符的比较,并找到一种处理误报的方法(即,哈希相等,但字符串不相等)。选择一个大的质数q可能有助于将误报的概率降低到可接受的水平。
票数 10
EN

Stack Overflow用户

发布于 2014-03-06 15:24:24

好的,所以答案是你需要缩进"for s“循环:

代码语言:javascript
复制
def Rabin_Karp_Matcher(text, pattern, d, q):
    n = len(text)
    m = len(pattern)
    h = pow(d,m-1)%q
    p = 0
    t =0
    result = []
    for i in range(m): # preprocessing
        p = (d*p+ord(pattern[i]))%q
        t = (d*t+ord(text[i]))%q

        for s in range(n-m):
            if p == t: # check character by character
                match = True
                for i in range(m):
                    if pattern[i] != text[s+i]:
                        match = False
                        break
                if match:
                    result = result + [s]
            if s < n-m:
                    t = (d*(t-ord(text[s+1])*h)+ord(text[s+m]))%q #index out of bounds here


    return result

这就给了我答案6,我想这就是你要找的。有趣的算法人。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22216948

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档