在这篇文章中,我们解释了使用滚动哈希技术、哈希表和暴力方法来寻找长度为K的不同子字符串的方法。
内容表。
- 问题陈述
- 方法1 - 蛮力
- 方法2 - 使用哈希表
- 方法3 - 滚动哈希算法
我们现在将深入研究 "长度为K的不同子串的数量 "这一问题。
问题说明
给出一串小写字母和一个整数k作为输入,打印所有可能的子串的数量,其中正好有k个不同的字符。
Enter the string: abcd
Enter k value: 1
Total substrings with exactly 1 distinct characters : 4
Enter the string: mqtt
Enter k value: 2
Total substrings with exactly 2 distinct characters : 3
Enter the string: aaaa
Enter k value: 2
Total substrings with exactly 2 distinct characters : 0
方法1 - 蛮力
假设字符串的长度为n,那么可能有__n__(n+1)/2个子串*。一个简单而直接的方法是生成所有子串,并检查它是否正好有k个独特的字符。
循环生成所有的组合,然后检查是否有独特的字符,这样做成本很高,复杂度也高。
n(n+1)/2 = (n^2+1)/2 = O(n^2)
所以,生成字符串的复杂度顺序是O(n^2)。
下一步是检查每一个组合,这将需要O(n),使得整体复杂度为O(n^3)。
空间复杂度 - O(n)
方法2 - 使用哈希表
考虑到字符串只包含小写字母。主要概念是维护子串的哈希表并检查唯一字符的数量。
什么是哈希表?它是一种实现数组数据类型的数据结构,其中每个数组都与值相关,即它有键和值。它也被称为哈希表。
- 首先,在程序中初始化计算所需的变量,如计数和存储字符的数组。
- 循环查找子串,并进一步查找其中的不同字符数。
- 最后,返回结果。
def count_k_dist(input_str, k):
n = len(input_str)
# Initializing res to 0,return after res after counting
res = 0
# To store count of characters from
# 'a' to 'z'
cnt = [0] * 27
# For considering all substring beginning with input_str[i]
for i in range(0, n):
dist_count = 0
# Initializing array with 0
cnt = [0] * 27
# Considering all substrings between str[i..j]
for j in range(i, n):
# If this is a new character for this
# substring, increment dist_count.
# ord(char) gives the ASCII value
if cnt[ord(input_str[j]) - 97] == 0:
dist_count += 1
# Increment count of current character
cnt[ord(input_str[j]) - 97] += 1
# If distinct character count becomes k,
# then increment result.
if dist_count == k:
res += 1
if dist_count > k:
break
return res
if __name__ == "__main__":
str1 = input("Enter the string: ")
k = int(input("Enter k value: "))
print("Total substrings with exactly", k,
"distinct characters : ", end="")
print(count_k_dist(str1, k))
时间复杂度:我们使用了两个嵌套的for循环,这使得时间复杂度为O(n*n)
空间复杂度:O(n)
方法3 - 滚动哈希算法
滚动散列(也被称为递归散列或滚动校验)是一个散列函数,输入在一个窗口中移动散列。
- 首先,找到长度为'l'的第一个子字符串的哈希值。
- 在它的帮助下,生成所有子串的哈希值,并将它们推入一个无序的集合。
- 计算该集合中不同值的数量。
- 因为有26个字符,所以用26来初始化x。
- 找到哈希值并将其添加到无序集合中(元素是唯一的,没有顺序)。
- 使用哈希值找出不同子字符串的数量。
# Python3 implementation of
x = 26
mod = 3001
# Function to find the required count
def count_substring(s, l):
# Variable to the hash_val
hash_val = 0
# Finding hash_val of substring
# (0, l-1) using random number x
for i in range(l):
hash_val = (hash_val * x + (ord(s[i]) - 97)) % mod
# Computing x^(l-1)
pow_l = 1
for i in range(l - 1):
pow_l = (pow_l * x) % mod
# Unordered set to add hash_val values
result = set()
result.add(hash_val)
# Generating all possible hash_val
for i in range(l, len(s)):
hash_val = ((hash_val - pow_l * (ord(s[i - l]) - 97) + 2 * mod) * x + (ord(s[i]) - 97)) % mod
result.add(hash_val)
# Print the result
print(len(result))
# Driver Code
if __name__ == "__main__":
str1 = input("Enter the string:")
k = int(input("Enter k value:"))
count_substring(str1, k)
时间复杂度:O(n)
空间复杂度。O(n)
希望你喜欢解决这个问题,并学会如何使用OpenGenus的这篇文章来解决这个问题。 祝你
今天愉快,继续学习。