【问题标题】:Algorithm optimizing算法优化
【发布时间】:2023-02-03 23:37:54
【问题描述】:

任务如下:

查找并计算给定输入主字符串 s 中所有可能子字符串的总和,通过进一步删除不必要的字母,您可以从中形成单词“tira”(课程缩写)。

示例,使用输入“tixratiyra”返回值 11: 1:蒂克斯拉蒂拉, 2:提克斯拉蒂拉,3:提克斯拉特伊拉,4:蒂克斯拉蒂你,5:比例RA,6:蒂克斯比一,7:提克斯拉蒂拉, 8: 蒂克斯阿蒂拉, 9: 提克斯拉蒂拉, 10: 钛xratiyra, 11: 吨伊克斯拉蒂拉.

我能够创建一段有效的代码,但它运行得不够快,它应该能够在 O(n) 时间内执行此任务,最大输入长度为 10^5。

我的代码,运行缓慢:

def count(s):
    start = timeit.default_timer()

    c = "bcdefghjklmnopqsuvwxyz"
    last_char = ""
    indexes = set()
    unique_indexes = []

    last_A = s.rfind("a")
    last_R = s.rfind("r", 0, last_A)
    last_I = s.rfind("i", 0, last_R)
    last_T = s.rfind("t", 0, last_I)

    unique_tiras = ""

    for i in range(len(s)):
        char = s[i]
        if char not in c:
            if char == "t":
                if i <= last_T:
                    indexes.add("t")
                    last_char = "t"
                    unique_tiras += str(i) + "t"
            
            elif char == "i" and last_char != "i":
                if i <= last_I and "t" in indexes:
                    indexes.add("i")
                    last_char = "i"
                    unique_tiras = unique_tiras.replace("t", "i")

            elif char == "r" and last_char != "r":
                if i <= last_R and ("t" and "i") in indexes:
                    indexes.add("r")
                    last_char = "r"
                    unique_tiras = unique_tiras.replace("i", "r")

            elif char == "a":
                if i <= last_A and ("t" and "i" and "r") in indexes:
                    last_char = "a"
                    unique_tiras = unique_tiras.replace("r", f"-{i};")
                    pairs = unique_tiras.split(";")
                    unique_tiras = ""

                    for elements in pairs:
                        if "-" in elements:
                            Tindex = elements.split("-")
                            unique_indexes.append((int(Tindex[0]), int(Tindex[1])))
                            unique_tiras += Tindex[0] + "r"
                        
                        else:
                            unique_tiras += elements

    if len(unique_indexes) < 1:
        print("found no tira substrings with input '", s[0:20], "'")
        print("indexing took a total of", timeit.default_timer()-start, "s")

        return 0
    
    print("found a total of", len(unique_indexes), "tira substrings with input '", s[0:20], "'") #, which are the following:
    #print(unique_indexes)
    print("indexing took a total of", timeit.default_timer()-start, "s")

    start = timeit.default_timer()

    unique_substrings = set()

    for tiras in unique_indexes:
        begin = 0

        while begin <= tiras[0]:
            end = tiras[1]

            while end <= len(s) - 1:
                unique_substrings.add((begin, end))
                end += 1
            
            begin += 1

    print("calculating suitable substrings took a total of", timeit.default_timer()-start, "s")
    print("found suitable substrings a total of")

    return len(unique_substrings)

if __name__ == "__main__":
    print(count("ritari")) # 0
    print(count("taikurinhattu")) # 4
    print(count("ttiirraa")) # 4
    print(count("tixratiyra")) # 11 
    print(count("aotiatraorirratap")) # 42

【问题讨论】:

  • 好像很难天真地,对于 len(s)+ 的每个可能的子串,s 的每个字母有多少(以正确的顺序)?也许更好地计算 s 的每个字母在主字符串中有多少然后做一些数学 - 你必须保存索引以确保字母是有序的。那至少应该减少搜索空间。
  • 如果主字符串有 1e5 个字符,正中间是您要查找的序列 'tira',并且这些字母没有出现在主字符串的其他任何位置,那么有多少个子字符串?

标签: python string optimization substring


【解决方案1】:

答案本身不是 O(n)。更像是 O(n²)。 例如,对于字符串“xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxtiraxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx”

答案是你可以为你的子串选择 40 个不同的开头,以及 40 个不同的结尾(有 39 个 x。所以你可以决定包含 0 到 39 x 作为前缀,0 到 39 x 作为后缀)。 这导致 1600 个可能的子串。

中间加上“tira”,大概是 (n/2)²

我在这里的意思不是说“这是不可能的”。有可能的。我即将这样做:D。

我的观点是,通过列举所有可能性是不可能的。因为如果您只是尝试很多子字符串,并计算那些有效的子字符串,那么您必须至少尝试所有有效的解决方案(加上无效的解决方案)。甚至假设您可以在 O(1) 中检查假设(您可能不能),这意味着计算时间至少与结果相同。

所以我们必须评估工作子串的数量,而不是实际枚举它们并检查它们

这是我的镜头

def minIndex(s, sub):
    if not sub[0] in s:
        return None,None
    i0=s.index(sub[0])
    ix=i0
    for c in sub[1:]:
        ss=s[ix+1:]
        if not c in ss:
            return None, None
        ix=ss.index(c)+ix+1
    return i0, ix


def mycount(s, sub):
    tot=0
    while True:
        a,b=minIndex(s, sub)
        if a is None:
            return tot
        tot+=(a+1)*(len(s)-b)
        s=s[a+1:]
    return tot

def count(s):
    return mycount(s, "tira")

if __name__ == "__main__":
    print(count("ritari")) # 0
    print(count("taikurinhattu")) # 4
    print(count("ttiirraa")) # 4
    print(count("tixratiyra")) # 11 
    print(count("aotiatraorirratap")) # 42

【讨论】:

    猜你喜欢
    • 2016-07-30
    • 1970-01-01
    • 2020-02-09
    • 2015-11-05
    • 2015-10-25
    • 2017-03-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多