查找最多包含K个重复字符的最长子字符串的长度

时间:2020-07-19 05:42:55

标签: python string algorithm binary-search

问题:给定整数n,k(1 <= n <= 100.000),(1 <= k <= n)。找到最多包含K个重复字符的最长子字符串的长度,并从原始字符串中找到子字符串中第一个元素的位置。 例子
输入:6、2个“ abbbaa” 输出:4 3 //这里,4是最大长度,3是子字符串'bbaa'的第一个元素在原始字符串中的位置。这样,每个字符在这里重复k次,就可以了

输入:3,1'abb' 输出:2,1 //是的,所需的子字符串是'ab' 我希望声明清楚,至少我尝试过,因为英语不是我的母语。

不知道如何针对该问题设计算法。从任务的陈述看,我应该使用二进制搜索的答案技术。

第一件事:我至少尝试在解决此问题的方式上发展自己的想法,所以是:

  1. 找到中间的字符串,然后将字符串切成两段,分别从0到mid + 1和mid到n。 (我使用Python编写代码,所以我认为在这里使用切片非常自然)
  2. 查找唯一字符的数量(我使用len(set(slice))),然后进行比较:如果第1个(左侧)切片的数量较大,则我们将right更改为mid,否则为left
  3. 所有这些说明都放在“ while right> left + 1”循环中。

到目前为止,还不错,但是我可能错过了某件事,或者这种想法并不是让子字符串的第一个元素的位置在给定字符串中的位置的有效方法。

代码(Python 3):使用binsearch查找第一个元素的位置

n, k = map(int, input().split())
s = input()
left = 0
right = n - 1

while (right > left + 1):
    mid = (left + right) // 2
    char1 = len(set(s[0:mid+1]))
    char2 = len(set(s[mid:n]))
    if char1 >= char2:
        right = mid
    else:
        left = mid
print(left + 1)

无需bin.search即可找到最长子字符串的长度的代码(我认为这会更容易,并且尽管天真的方法也可以工作)

n, k = map(int, input().split())
s = input()
letters = [0] * 26
max_len = 0
for i in range(len(s)):
    letters[ord(s[i]) - ord('a')] = letters[ord(s[i]) - ord('a')] + 1
for i in range(0, 26):
    if letters[i] >= k:
        max_len = max_len + k
    else:
        max_len = max_len + letters[i]
print(max_len)

1 个答案:

答案 0 :(得分:1)

您的方法很贪婪,不会得到正确的结果。考虑输入4 4 ccab-您的二进制搜索代码将返回2,但应返回1(整个字符串都不错)。要解决此问题,您可以使用称为两个指针的方法。我们将两个指针a和b定义为当前正在考虑的子字符串的开头和结尾。我们还需要记住在当前子字符串中每个字母出现了多少次。首先,将a和b设置为0。然后尝试通过将当前子字符串的末端移动1(b = b + 1)来扩展当前子字符串,然后像这样将字母s [b]的出现次数增加1。超过K,这意味着我们当前的字符串不再有效。为了使其再次有效,我们需要将其移到所有子字符串(a,b)出现少于或恰好K次的位置。为此,我们只需将a递增1并递减oc [s [a]]直到oc [s [b]] <= k。时间复杂度是线性的,因为我们将b精确地增加n次,最多将a增加n次。在每一步中,我们还检查b-a + 1> max_len是否设置为max-len到b-a + 1,开始设置为a。

n, k = map(int, input().split())
s = input()
a = 0
oc = [0]*26
max_len = 0
first = -1

for b in range(0, n):
    oc[ord(s[b])-ord('a')]+=1
    while(oc[ord(s[b])-ord('a')]>k):
        oc[ord(s[a])-ord('a')]-=1
        a+=1
    if b-a+1>max_len:
        max_len=b-a+1
        first=a+1

print(first)
print(max_len)

oc是一个数组,用于在子字符串中存储字母的出现。