Underscorify Substring

refer to: AlgoExpert

Input: string, substring

Output: add underscore at the start and the end of substring found in the string. if overlap or sit side by side, only add underscore at the leftmost and the rightmost positions

Analysis: 

step 1

 step 2

 step 3

 time and space complexity

string.find: O(m+n)

traverse length n

upperbound: n(m+n)

def underscorifySubstring(string, substring):
    locations = collapse(getLocations(string, substring))
    return underscorify(string, locations)

def getLocations(string, substring):
    locations = []
    startIdx = 0;
    while startIdx < len(string):
        nextIdx = string.find(substring, startIdx);
        if nextIdx != -1: #if substring is found, add the start index and the end index
            locations.append([nextIdx, nextIdx + len(substring)])
            startIdx = nextIdx + 1 #continue to traverse the next one
        else:
            break # if not found, break
    return locations

def collapse(locations): # address the special cases: 1. overlap 2. sit side by side
    if not len(locations): # if the locations array is empty, return []
        return locations
    newLocations = [locations[0]] # newLocations starts from the first element in the 2d array
    previous = newLocations[0] #initiate the previous(the first position)
    for i in range(1, len(locations)): # check the following positions
        current = locations[i] #current defines the following position, from the second array in locations
        if current[0] <= previous[1]: #[1,3] [2,4] current[0] = 2, previous[1] = 3, overlapping
            previous[1] = current[1] #[1,3]->[1,4] # update previous
        else: # no overlapping or sit side by side
            newLocations.append(current) # append the whole currect array
            previous = current # update the previous to current
    return newLocations

def underscorify(string, locations): # add underscore
    locationsIdx = 0
    stringIdx = 0
    inBetweenUnderscores = False
    finalChars = []
    i = 0
    while stringIdx < len(string) and locationsIdx < len(locations): # while we are in the middle od string and the locations array
        if stringIdx == locations[locationsIdx][i]:
            finalChars.append("_")
            inBetweenUnderscores = not inBetweenUnderscores # finished adding _ for one array
            if not inBetweenUnderscores: #false(initial)-> true -> false(one pass finished, move to another) -> true->false
                locationsIdx += 1 # go to the next array
            i = 0 if i == 1 else 1 # if i =1, ->i = 0;   if i = 0, ->i = 1, i have two potions: 0 or 1
        finalChars.append(string[stringIdx]) # if stringIdx != locations[locationsIdx][i], append the substring directly
        stringIdx += 1
    if locationsIdx < len(locations): # finished traversing the string 
        finalChars.append("_")
    elif stringIdx < len(string): # finished traversing the locations
        finalChars.append(string[stringIdx:])
    return "".join(finalChars)
 
原文地址:https://www.cnblogs.com/LilyLiya/p/14816347.html