import random
import time

# Searching for a single value few times is best done by built-in functions
# Searching repeatedly for many values might be improved by additional ideas
# like e.g. indicator (characteristic) vector.

#str = "Searching repeatedly for many values might be improved by additional ideas"
str = "soo_many"

print( str.find("many") )
print( str.index("many") )
print( "many" in str )

def allSubstrings( str ):
    all = []
    for i in range( 0, len(str) ):
        for j in range(i+1, len(str)+1 ):
            all.append( str[i:j])
    return all

all = allSubstrings( str )

print( all )
print( "\n".join(all) )
print( len(str), len( all) )
print()

# BTW, how many characters in total in all substrings?
# add: N*1 + (N-1)*2 + (N-2)*3 + ... 2*(N-1) + 1*N
# it is a sum( i *(N+1-i), i = 1..N ) = N(N+1)(N+2)/6 = O(N^3) !!

# More advanced idea of so-called "tries" is not explored here

# reverse a string
print( str[::-1] )
print( list(reversed(str)) )
print()

# create a set of strings
set1 = { e for e in all }
print( set1 )
# note the size of the set -- only unique elements are in it

# create a set of reversed strings
sRev = str[::-1]
allRev = allSubstrings( sRev )
set2 = { e for e in allRev }
print( set2 )

print( len(all), len(set1), len(set2) )

# check how many reversed strings are there among the original ones
def strMatches( setStr1, setStr2 ):
    matches = []
    for str in setStr1:
        if str in setStr2:
            matches.append( str )
    return matches

print( "Matches:\n", strMatches(set1, set2) )

# search in a list
def allMatches1( str ):
    strs1 = allSubstrings( str )
    strs2 = allSubstrings( str[::-1] )
    allM = []
    t1 = time.time()
    for str in strs1:
        if str in strs2:
            allM.append(str)
    t2 = time.time()
    print ( "All matches:" )
    print ( allM )
    print( "time", "%6.2f" % (t2 - t1) )

# search in a set
def allMatches2( str ):
    strs1 = allSubstrings( str )
    set1 = { e for e in strs1 }
    strs2 = allSubstrings( str[::-1] )
    set2 = { e for e in strs2 }
    t1 = time.time()
    print ( "All matches:" )
    allM =  strMatches ( set1, set2  )
    t2 = time.time()
    print ( allM )
    print( "time", "%6.2f" % (t2 - t1) )


str = "The data files are big.  Create a smaller copy of a data file using your text editor"
str = str * 2
print( str )
print (  str[::-1] ) # reversed string

allMatches1( str )

allMatches2( str )










