给定一个字符串,使用 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 现场工作专业课程和学生竞争性编程现场课程。