We can arrange the following tables through a preprocessing step
line name space
0 dir1 0
1 dir11 1
2 dir12 1
4 dir121 2
6 dir2 0
line space
3 2
7 1
The basic idea is for each img file, we match the closest line that is less that is at least 1 less then the img line that also contains 1 less space than it.
We continue looking for 1 less space until all the spaces are exhausted (root directory is reached).
Notice that the child of every parent is 1 tab more than it. Using this as our guiding principle, we can model our tree.
So the solution is just iterating through the entire tree, and keeping track of the largest path for a file.
A file is distinguished with a '.'
Because our 'tree' is a txt file, we'll be modeling our tree using a stack, which is just effective as using recursion.
Our stack begins with the root directory, and we'll be adding elements to our stack in a pre-order fashion. That is, elements continue to be added, until we find that the next child is not a child of the previous top element. We do this by comparing the number of tabs of the current node, to the top of the stack.
In the process, we collect the size on the current file path. And if the node is a file, we update the current max path.
Otherwise, if our node is not a child, we'll have to 'recurse back', until we find a position where it is. That is, our stack can only grow in the number of tabs it has. For example, we can have 1->2->3->4... but not 1->2->2. The second while loop in the code takes care of this for us.
For example, consider that we are in subsubdir1 in the tree above. In other to get to subdir2, it would not make sense just to recurse back once and go to subdir1. We'll have to continue recursing back until subdir2 tabs are > dir1.
Similar idea as before, just cleaned up. The algorithm comes down to knowing which position in the current file is by using the number of tabs as a guiding principle.
Complexity: O(n) time and space
import reclassSolution:deflengthLongestPath(self,input):""" :type input: str :rtype: int """ifnotinput:return0# split by tab delimitor tree = re.split('(\t|\n)', input)# clean for simplier processing later tree = [elm for elm in tree if elm !='\n'and elm !='']# begin the preorder + 1 for dir + '/' s = [(len(tree[0])+1,0)] abs_max =0# iterate through elementsiter=1whileiter<len(tree): file = tree[iter] parent_len = s[-1][0] parent_lvl = s[-1][1] tab_cnt =0whileiter<len(tree)and file =='\t':iter+=1 file = tree[iter] tab_cnt +=1# step into the correct parent of the treewhile tab_cnt != parent_lvl +1: s.pop() parent_len = s[-1][0] parent_lvl = s[-1][1]if'.'notin file:# is directory, add 1 for '/' s.append((parent_len +len(file) +1, tab_cnt))else:# is file, no need to recurse down abs_max =max(abs_max, parent_len +len(file))iter+=1return abs_max