1
\$\begingroup\$

This is the Substring Game! challenge from HackerEarth:

Watson gives Sherlock a string (let's denote it by S). Watson calculates all the substrings of S in his favourite order.

According to the Watson's favourite order, all the substrings starting from first character of the string will occur first in the sorted order of their length, followed by all the substrings starting from the second character of the string in the sorted order of their length, and so on.

For example, suppose S = abc. Then, all the substrings of S as per Watson's favourite order are:

  1. a
  2. ab
  3. abc
  4. b
  5. bc
  6. c

Watson will ask Sherlock 'q' questions. In each question, Watson will give Sherlock a number and Sherlock has to speak the substring on that number. If there is no possible substring, then Sherlock has to speak -1.

Can the below code be improved to run in \$o(n^2)\$ complexity?

str=raw_input()
q=int(raw_input())
num=raw_input().split(' ')
substr=[]
for i,s in enumerate(str):
 #print i,s
 for j in range(i+1,len(str)+1):
 #print j
 substr.append(s+str[i+1:j])
#print substr
for i in range(0,q):
 try:
 print substr[int(num[i])-1]
 except IndexError:
 print -1

Sample Input
First line is the string - abc
Second line is the number of substrings asked- 2
Third line is the position of the substrings to return from the list of substrings- 2 5

The list of substrings would be ['a','ab','abc','b','bc','c']
Sample Output
ab
bc

Gareth Rees
50.1k3 gold badges130 silver badges210 bronze badges
asked Jan 3, 2018 at 8:28
\$\endgroup\$
0

1 Answer 1

3
\$\begingroup\$
  • Don't name things str.
  • Use a list comprehension to build substr.
  • s+str[i+1:j] would be simpler as str[i:j].
  • Iterate through num, rather than the range(q)
  • Your can wrap your print keywords with (), so this is a bit more Python 3 compatible.

This can get:

S = raw_input()
q = int(raw_input())
nums = map(int, raw_input().split(' '))
substr = [
 S[i:j+1]
 for i in range(len(S))
 for j in range(i, len(S))
]
for i in nums:
 try:
 print(substr[i-1])
 except IndexError:
 print(-1)

However this uses \$O(S^3)\$ of memory. So about \10ドル^{15}\,ドル or 1 petabyte of storage. So your code doesn't feasibly work. Instead work things in the reverse order.

If you have the number \5ドル\,ドル you know it's \5ドル \gt 3\,ドル \5ドル-3 = 2\,ドル \2ドル \le 2\,ドル and so is S[1:1+2]. And so I'd use:

S = raw_input()
q = raw_input()
nums = map(int, raw_input().split(' '))
for num in nums:
 for i, s in enumerate(reversed(range(1, len(S)+1))):
 if num <= s:
 print(S[i:i+num])
 break
 num -= s
 else:
 print(-1)

Which is still better than yours in terms of time complexity, as it's \$O(nS)\,ドル \$~10^8\,ドル rather than \$O(n + S^2)\,ドル \10ドル^3 + 10^{10}\$.

answered Jan 3, 2018 at 9:38
\$\endgroup\$
1
  • \$\begingroup\$ (Having space complexity exceed time complexity spells non-RAM.) \$\endgroup\$ Commented Jan 9, 2018 at 12:20

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.