有没有办法在 O(n) 时间内打印字符串的所有子字符串?

Posted

技术标签:

【中文标题】有没有办法在 O(n) 时间内打印字符串的所有子字符串?【英文标题】:Is there a way to print all substrings of a string in O(n) time? 【发布时间】:2020-07-19 16:59:37 【问题描述】:

我有一个输入 abcde。我正在尝试输出如下内容:

a
ab
abc
abcd
abcde
b
bc
bcd
bcde
c
cd
cde
d
de
e

我无法编写没有嵌套循环的代码。我的问题是 O(n) 时间复杂度的问题的解决方案是什么?

我的代码如下:

s = "abcde"  
for i in range(len(s)):
    for x in range(i, len(s) + 1):
        a = s[i:x]
        if a != "": print(a)

【问题讨论】:

如果n 应该是输入的长度,那是不可能的。 顺序重要吗? 不,没关系 【参考方案1】:

有没有办法在O(N)时间打印字符串的所有子字符串?

不,没有。这在数学上是不可能的。

长度为N 的字符串有O(N^2) 子字符串。您不能在O(N) 时间打印O(N^2) 字符串。即使字符串全部(单独)O(1) 打印。 (他们不是。)

即使是并行性也无法将您带到O(N)。如果(假设)有一个P > N 处理器来生成字符串,打印它们是一个您无法并行化的过程。


为了记录,可以以避免显式嵌套循环的方式对此进行编码。但这并没有改变比 O(N^3) 更好的解决方案的基本数学不可能性。

【讨论】:

【参考方案2】:

让我们在没有嵌套循环的情况下执行此操作! 这是一个带有random 库的游戏,但执行时间与您的代码相似。

from random import randint
list1=[]
str1='abcde'
while len(list1)!=int(((len(str1)+1)*len(str1))//2):
    i=randint(0,len(str1))
    j=randint(0,len(str1))
    i,j=max(i,j),min(i,j)
    if i!=j:
        a=str1[j:i]
        if a not in list1:
            list1.append(a)
            print(a)

如果是字符串str1 = 'abcdef',则打印:

de
abcdef
cdef
abc
ef
d
c
abcd
b
abcde
def
bcde
f
bcdef
a
bcd
cd
e
ab
cde
bc 

现在,如果您希望数据按照您指定的顺序,请使用sort

list1.sort()

【讨论】:

这不是所要求的O(N)。它是O(N^3)。没有O(N) 解决方案。 而且甚至不起作用。【参考方案3】:

如果您还打印子字符串,时间复杂度会上升到 O(N^3),因为每个子字符串的长度是 O(N),因此您将在 O(N) 时间内打印 O(N^2) 子字符串,每个时间复杂度都为整体复杂度的O(N^3)。请参阅重复的Find all possible substring in fastest way。

附带说明一下,您可以通过将内部循环更改为从i+1 开始来避免空字符串检查,这是一个(非常)轻微的优化。

s = "abcde"
for i in range(len(s)):
    for x in range(i+1, len(s)+1):
        a = s[i:x]
        print a

【讨论】:

这并不能解决 OP 问题。他不需要嵌套循环 没有嵌套循环的解决方案是可能的 这不是关于嵌套循环,而是关于时间复杂度。也许没有嵌套循环的解决方案是可能的,但不可能在少于O(N^3) 的时间内打印O(N^3) 个字符。 这个答案不相关,这不是问的!

以上是关于有没有办法在 O(n) 时间内打印字符串的所有子字符串?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在少于 O(n) 的时间内找到集合中的最小元素?

在 O(log(n)) 时间内从 std::set 中随机选择一个元素

检查两个排序的字符串在 O(log n) 时间内是不是相等

解 消失的数字

给定 O(1) 或 O(log N) 时间中的源集,有没有办法在数学上生成排序排列和数组的给定索引?

使用 awk 打印从第 n 到最后的所有列