git-subtree-dir: users/wpcarro git-subtree-mainline:464bbcb15cgit-subtree-split:24f5a642afChange-Id: I6105b3762b79126b3488359c95978cadb3efa789
		
			
				
	
	
		
			93 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			93 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import random
 | 
						|
from collections import deque
 | 
						|
 | 
						|
def exists(pattern, tree):
 | 
						|
    """
 | 
						|
    Return true if `pattern` exists in `tree`.
 | 
						|
    """
 | 
						|
    if len(pattern) == 0:
 | 
						|
        return True
 | 
						|
    if len(pattern) == 1:
 | 
						|
        for branch in tree:
 | 
						|
            if branch[0] == pattern[0]:
 | 
						|
                return True
 | 
						|
        return False
 | 
						|
    for branch in tree:
 | 
						|
        if branch[0] == pattern[0]:
 | 
						|
            return exists(pattern[1:], branch[1])
 | 
						|
    return False
 | 
						|
 | 
						|
# Branch :: (Char, [Branch])
 | 
						|
# SuffixTree :: [Branch]
 | 
						|
 | 
						|
def suffix_tree(xs):
 | 
						|
    """
 | 
						|
    Create a suffix tree from the input string, `xs`.
 | 
						|
    """
 | 
						|
    root = []
 | 
						|
    for i in range(len(xs)):
 | 
						|
        curr = xs[i:]
 | 
						|
        parent = root
 | 
						|
        for c1 in curr:
 | 
						|
            grafted = False
 | 
						|
            for c2, children in parent:
 | 
						|
                if c1 == c2:
 | 
						|
                    grafted = True
 | 
						|
                    parent = children
 | 
						|
            if grafted:
 | 
						|
                continue
 | 
						|
            else:
 | 
						|
                children = []
 | 
						|
                child = (c1, children)
 | 
						|
                parent.append(child)
 | 
						|
                parent = children
 | 
						|
    return root
 | 
						|
 | 
						|
def suffix_tree(x):
 | 
						|
    """
 | 
						|
    Creates a suffix from the input string, `x`. This implementation uses a
 | 
						|
    stack.
 | 
						|
    """
 | 
						|
    result = [None, []]
 | 
						|
    q = deque()
 | 
						|
    for i in range(len(x)):
 | 
						|
        q.append((result, x[i:]))
 | 
						|
    while q:
 | 
						|
        parent, x = q.popleft()
 | 
						|
        s = []
 | 
						|
        s.append((parent, x))
 | 
						|
        while s:
 | 
						|
            parent, x = s.pop()
 | 
						|
            if not x:
 | 
						|
                continue
 | 
						|
            c, rest = x[0], x[1:]
 | 
						|
            grafted = False
 | 
						|
            for child in parent[1]:
 | 
						|
                if c == child[0]:
 | 
						|
                    s.append((child, rest))
 | 
						|
                    grafted = True
 | 
						|
            if not grafted:
 | 
						|
                child = [c, []]
 | 
						|
                parent[1].append(child)
 | 
						|
                s.append((child, rest))
 | 
						|
    return result[1]
 | 
						|
 | 
						|
################################################################################
 | 
						|
# Tests
 | 
						|
################################################################################
 | 
						|
 | 
						|
x = random.choice(["burrito", "pizza", "guacamole"])
 | 
						|
tree = suffix_tree(x)
 | 
						|
for branch in tree:
 | 
						|
    print(branch)
 | 
						|
 | 
						|
for _ in range(3):
 | 
						|
    n = len(x)
 | 
						|
    i, j = random.randint(0, n), random.randint(0, n)
 | 
						|
    pattern = x[min(i, j):max(i, j)]
 | 
						|
    print("Checking \"{}\" for \"{}\" ...".format(x, pattern))
 | 
						|
    print("Result: {}".format(exists(pattern, tree)))
 | 
						|
    pattern = random.choice(["foo", "bar", "baz"])
 | 
						|
    print("Checking \"{}\" for \"{}\" ...".format(x, pattern))
 | 
						|
    print("Result: {}".format(exists(pattern, tree)))
 | 
						|
    print()
 |