5

I have an input abcde. I'm trying to output something like this:

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

I can't make a code which is without nested loops. My question is what is the solution of this problem with O(n) time complexity?

My code is given below:

s = "abcde"  
for i in range(len(s)):
    for x in range(i, len(s) + 1):
        a = s[i:x]
        if a != "": print(a)
Ryan
  • 827
  • 9
  • 26
Azmain1234
  • 77
  • 1
  • 7

3 Answers3

4

Is there a way to print all substrings of a string in O(N) time?

No there isn't. It is mathematically impossible.

There are O(N^2) substrings of a string of length N. You cannot print O(N^2) strings in O(N) time. Not even if the strings were all (individually) O(1) to print. (Which they aren't. The average substring length is also a function of N.)

Even parallelism won't get you to O(N). If (hypothetically) had a P > N processors to generate the strings, printing them is a process that you cannot parallelize.


For the record, it is possible to code this in ways that avoid explicit nested loops. But this doesn't alter the fundamental mathematical impossibility of a solution that is better than O(N^3).

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
0

If you're also printing the substrings, time complexity goes up to O(N^3) because each substring is O(N) in length, so you'll be printing O(N^2) substrings in O(N) time each for an overall complexity of O(N^3). See the duplicate Find all possible substring in fastest way.

As a side note, you can avoid the empty-string check by changing the inner loop to begin at i + 1, which is a (very) slight optimization.

s = "abcde"
for i in range(len(s)):
    for x in range(i+1, len(s)+1):
        a = s[i:x]
        print a
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
aeternalis1
  • 675
  • 4
  • 7
-1

Lets do this without a nested loop!
This a game with random library, but the execution time is similar to your code.

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)

if the string, str1 = 'abcdef', it prints:

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

Now if you want your data in the order you specified, use sort:

list1.sort()
Joshua Varghese
  • 5,082
  • 1
  • 13
  • 34