Ответ 1
Хороший вопрос для упражнений в основных строковых операциях. Я больше не помню суффикс-дерево;) Но, как вы заявили: теория-мудрый, вы настроены.
Как предварительно обработать дерево листьями потомков?
wikipedia-stub на эту тему немного запутан. Вам нужно только знать, если вы являетесь самым внешним не-leaf- node с детьми n >= k
. Если вы нашли подстроку от root-node к этому во всей строке, суффикс-дерево сообщает вам, что существуют n
возможные продолжения. Таким образом, должно существовать n
места, где происходит эта строка.
После этого, как быстро вычислить глубину?
Простая ключевая концепция этой и многих подобных проблем заключается в том, чтобы выполнить поиск по глубине: в каждом Node задайте дочерние элементы для их значения и верните максимальное значение родительскому элементу. Окончательный результат получит root-node.
Как рассчитываются значения, различаются проблемы. Здесь у вас есть три возможности для каждого node:
- node не имеют дочерних элементов. Его лист - node, результат недействителен.
- Каждый ребенок возвращает неверный результат. Его последний не-лист- node, результат равен нулю (после символа node больше символов). Если этот node имеет дочерние элементы
n
, то конкретизированная строка каждого ребра из корня в этот node появляетсяn
раз во всей строке. Если нам нужны не менееk
узлы иk > n
, результат также недействителен. - Один или несколько листов возвращают что-то действительное. Результатом является максимальное значение возвращаемого значения плюс, длина строки привязала к нему ребро.
Конечно, вам также нужно вернуть корреспондирующий node. В противном случае вы узнаете, как долго длится повторяющаяся подстрока, но не там, где она есть.
код
Сначала вы должны попытаться закодировать это самостоятельно. Построение дерева прост, но не тривиально, если вы хотите собрать всю необходимую информацию. Тем не менее, вот простой пример. Обратите внимание: каждая проверка работоспособности выбывает из строя, и все будет терпеть неудачу, если вход каким-то образом недействителен. Например. не пытайтесь использовать какой-либо другой корневой индекс, чем один, не ссылайтесь на узлы как на родителя, на которые раньше не указывались дочерние элементы и т.д. Много места для улучшения * hint;) *.
class Node(object):
def __init__(self, idx):
self.idx = idx # not needed but nice for prints
self.parent = None # edge to parent or None
self.childs = [] # list of edges
def get_deepest(self, k = 2):
max_value = -1
max_node = None
for edge in self.childs:
r = edge.n2.get_deepest()
if r is None: continue # leaf
value, node = r
value += len(edge.s)
if value > max_value: # new best result
max_value = value
max_node = node
if max_node is None:
# we are either a leaf (no edge connected) or
# the last non-leaf.
# The number of childs have to be k to be valid.
return (0, self) if len(self.childs) == k else None
else:
return (max_value, max_node)
def get_string_to_root(self):
if self.parent is None: return ""
return self.parent.n1.get_string_to_root() + self.parent.s
class Edge(object):
# creating the edge also sets the correspondending
# values in the nodes
def __init__(self, n1, n2, s):
#print "Edge %d -> %d [ %s]" % (n1.idx, n2.idx, s)
self.n1, self.n2, self.s = n1, n2, s
n1.childs.append(self)
n2.parent = self
nodes = {1 : Node(1)} # root-node
string = sys.stdin.readline()
k = int(sys.stdin.readline())
for line in sys.stdin:
parent_idx, child_idx, start, length = [int(x) for x in line.split()]
s = string[start-1:start-1+length]
# every edge constructs a Node
nodes[child_idx] = Node(child_idx)
Edge(nodes[parent_idx], nodes[child_idx], s)
(depth, node) = nodes[1].get_deepest(k)
print node.get_string_to_root()