📌  相关文章
📜  具有相同字符的最大子字符串(1)

📅  最后修改于: 2023-12-03 15:07:06.620000             🧑  作者: Mango

最长连续相同字符子串

在字符串处理中,经常会遇到需要找到最长连续相同字符子串的需求。这篇文章将介绍如何通过算法实现查找最长连续相同字符子串,并给出代码实现。

算法原理
笨办法

最直接的方法是对所有可能的子串进行遍历,对每个子串计算其中相同字符的数量。时间复杂度为 $O(n^3)$,非常低效。不推荐使用。

优化一

由于要查找的是连续的子串,而不是无序的子串,因此可以通过滑动窗口的方式进行处理。记录两个指针,分别指向子串的起始位置和结束位置,并记录当前子串中最长的字符数量。每次移动结束位置指针,若遇到新的字符与当前子串中的字符不同,则更新起始位置指针的位置到与结束位置指针相同的字符位置,重新开始计算字符数量。时间复杂度为 $O(n)$。

def longest_consecutive_same_char(s: str) -> int:
    max_len = 1
    cur_len = 1
    n = len(s)
    for i in range(1, n):
        if s[i] == s[i-1]:
            cur_len += 1
        else:
            max_len = max(max_len, cur_len)
            cur_len = 1
    return max(max_len, cur_len)
优化二

通过优化一,时间复杂度已经达到了 $O(n)$ 的级别,但是还有一些细节可以优化。比如当字符串全部都是相同字符时,优化一的算法会继续遍历所有字符,浪费时间。因此,我们可以在每次更新字符数量时,通过比较当前字符数量和已知最长字符数量,如果当前字符数量已经比已知最长字符数量大,则更新最长字符数量。时间复杂度依然为 $O(n)$。

def longest_consecutive_same_char(s: str) -> int:
    max_len = 1
    cur_len = 1
    n = len(s)
    for i in range(1, n):
        if s[i] == s[i-1]:
            cur_len += 1
        else:
            max_len = max(max_len, cur_len)
            cur_len = 1
        if cur_len > max_len:
            max_len = cur_len
    return max_len
优化三

通过优化二,算法已经非常高效,但是我们可以再进一步优化。当我们找到一个长度等于 $k$ 的连续相同字符子串时,我们肯定不需要再遍历长度小于 $k$ 的子串了。由于起始位置指针的增加速度比结束位置指针的增加速度快,因此我们可以通过减小起始位置指针的增加速度,只遍历长度大于等于已知最长连续相同字符子串长度的子串。我们可以通过限定起始位置指针和结束位置指针之间的距离不超过已知最长连续相同字符子串长度来实现该优化。时间复杂度依然为 $O(n)$。

def longest_consecutive_same_char(s: str) -> int:
    max_len = 1
    cur_len = 1
    n = len(s)
    start = 0
    for i in range(1, n):
        if s[i] == s[i-1]:
            cur_len += 1
        else:
            max_len = max(max_len, cur_len)
            if cur_len >= max_len:
                start = i - cur_len
            cur_len = 1
        if i - start + 1 > max_len:
            max_len = i - start + 1
    return max_len
总结

本文介绍了三种不同优化级别的算法,实现查找最长连续相同字符子串的需求。虽然算法的复杂度相差不大,但是细节和实现方式的优化对算法的效率有着巨大的影响。在实际应用中,算法的效率往往决定着程序的性能和用户体验。因此,我们需要在保证正确性的前提下,尽可能地优化算法的效率,以提高程序的性能。