📜  使用 Rabin Karp 算法计算字符串的不同子串

📅  最后修改于: 2021-10-27 07:21:04             🧑  作者: Mango

给定一个字符串,使用 Rabin Karp 算法计算不同子字符串的数量。

例子

Input  : str = “aba”
Output : 5
Explanation :
Total number of distinct substring are 5 - "a", "ab", "aba", "b" ,"ba" 

Input  : str = “abcd”
Output : 10
Explanation :
Total number of distinct substring are 10 - "a", "ab", "abc", "abcd", "b", "bc", "bcd", "c", "cd", "d" 

方法:

先决条件:模式搜索的 Rabin-Karp 算法

计算当前字符的当前哈希值并存储
在字典/地图中以避免重复。

要按照 Rabin-Karp 算法计算哈希(滚动哈希),请执行以下操作:

Rabin 和 Karp 建议的哈希函数计算一个整数值。用于字符串的整数值是一个字符串的数值。例如,如果所有可能的字符都是从 1 到 10,那么“122”的数值将是 122。可能的字符数大于 10(一般为 256)并且模式长度可能很大。因此,数值实际上不能存储为整数。因此,数值是使用模算术计算的,以确保哈希值可以存储在整数变量中(可以适合内存字)。要进行重新散列,我们需要去掉最高有效位并为 in 哈希值添加新的最低有效位。使用以下公式进行重新散列。

hash( txt[s+1 .. s+m] ) = ( d ( hash( txt[s .. s+m-1]) – txt[s]*h ) + txt[s + m] ) mod q

hash( txt[s .. s+m-1] ) :移位s处的哈希值。
hash( txt[s+1 .. s+m] ) : 下一个移位(或移位s +1)的哈希值
d:在字母字符数
q : 质数
h: d^(m-1)

这个想法与我们评估数学表达式类似。例如,我们有一个字符串“1234”,让我们计算子字符串“12”的值是 12,我们想要计算子字符串“123”的值,这可以计算为 ((12)*10+3 )=123,这里应用类似的逻辑。

Python3
# importing libraries
import sys
import math as mt
t = 1
# store prime to reduce overflow
mod = 9007199254740881
 
for ___ in range(t):
 
    # string to check number of distinct substring
    s = 'abcd'
 
    # to store substrings
    l = []
 
    # to store hash values by Rabin Karp algorithm
    d = {}
 
    for i in range(len(s)):
        suma = 0
        pre = 0
 
        # Number of input alphabets
        D = 256
 
        for j in range(i, len(s)):
 
            # calculate new hash value by adding next element
            pre = (pre*D+ord(s[j])) % mod
 
            # store string length if non repeat
            if d.get(pre, -1) == -1:
                l.append([i, j])
            d[pre] = 1
 
    # resulting length
    print(len(l))
 
    # resulting distinct substrings
    for i in range(len(l)):
        print(s[l[i][0]:l[i][1]+1], end=" ")


输出
10
a ab abc abcd b bc bcd c cd d 

时间复杂度: O(N 2 ),N 是字符串的长度

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程