refer to: AlgoExpert
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