# update the parent and child
Add(parent!.edges, edge);
child!.parentEdge := edge;
return edge; end );
InstallMethod( ParentNode, "for suffix tree nodes",
true,
[ IsSuffixTreeNode and IsDefaultSuffixTreeNodeRep ], 0, function( v ) if v!.parentEdge = 0then
return 0; else
return v!.parentEdge!.parent; fi; end );
InstallMethod( \=, "for suffix tree elements",
IsIdenticalObj,
[IsSuffixTreeElement, IsSuffixTreeElement], 0,
IsIdenticalObj );
InstallOtherMethod( \[\], "for suffix trees and positive integers",
true,
[IsSuffixTree and IsDefaultSuffixTreeRep,
IsPosInt], 0, function( st, i )
local n;
n := Length(st!.patterns[i][2]);
return st!.patterns[i][2]{[1..n-1]}; end );
InstallMethod( AddInternalSuffixTreeNode, "for suffix tree edges, integers, and internal suffix tree nodes",
true,
[IsSuffixTreeEdge and IsDefaultSuffixTreeEdgeRep,
IsPosInt,
IsInternalSuffixTreeNode and IsDefaultInternalSuffixTreeNodeRep], 0, function( edge, location, node )
local oldChild, pattern, start, lend;
# get the information needed to construct the label on the # new edge. This must happen before updating the old edge
pattern := edge!.label[1];
start := edge!.label[2] + location;
lend := edge!.label[3];
return pattern{[start..lend]}; end );
InstallMethod( LabelOfSuffixTreeNode, "for internal suffix tree nodes",
true,
[ IsInternalSuffixTreeNode and IsDefaultInternalSuffixTreeNodeRep ], 0, function( node )
local pattern;
if Length(node!.label[1]) = 0then # special case for root node
return []; fi;
pattern := node!.label[1][2];
return pattern{[node!.label[2]..node!.label[3]]}; end );
InstallMethod( LabelOfSuffixTreeEdge, "for suffix tree edges",
true,
[ IsSuffixTreeEdge and IsDefaultSuffixTreeEdgeRep ], 0, function(edge)
local pattern, start, lend;
pattern := edge!.label[1][2];
start := edge!.label[2];
lend := edge!.label[3]; if lend < start then # add on the termination symbol
lend := Length(pattern); fi;
Assert( 1, start <= Length(pattern), "Start of pattern is longer than pattern" );
return pattern{[start..lend]}; end );
InstallMethod( SuffixTreeEdgeStartingAt, "for an internal suffix tree node and an object",
true,
[IsInternalSuffixTreeNode and IsDefaultInternalSuffixTreeNodeRep,
IsObject], 0, function( node, object )
local edge, label;
for edge in node!.edges do
label := LabelOfSuffixTreeEdge(edge); if Length(label) > 0 and object = label[1] then
return edge; fi;
od;
return fail; end );
InsertIntoDynamicForest := function(u)
local v, w;
v := ParentNode(u);
if IsExternalSuffixTreeNode(u) then
u!.dynTree := CreateDynamicTree(u);
LinkDynamicTrees(u!.dynTree, v!.dynTree); elif u!.marked and IsBound(u!.dynTree) then
Assert(1, IsInternalSuffixTreeNode(u), "$u$ is marked and old, should be internal");
CutDynamicTree(u!.dynTree); else
Assert(1, IsInternalSuffixTreeNode(u) and not IsBound(u!.dynTree), "$u$ should be a new internal node here!");
u!.dynTree := CreateDynamicTree(u); # NOTE: Major assumption here! The edge containing the child # that was not newly created is the first one. If the order in # which edges are created when a new internal node is put into # the suffix tree, then this will probably fail to be true
w := u!.edges[1]!.child;
if not u!.marked then if RootOfDynamicTree(v!.dynTree) = RootOfDynamicTree(w!.dynTree) then
CutDynamicTree(w!.dynTree);
LinkDynamicTrees(u!.dynTree, v!.dynTree);
LinkDynamicTrees(w!.dynTree, u!.dynTree); else
LinkDynamicTrees(u!.dynTree, v!.dynTree); fi; else if RootOfDynamicTree(v!.dynTree) = RootOfDynamicTree(w!.dynTree) then
CutDynamicTree(w!.dynTree);
LinkDynamicTrees(w!.dynTree, u!.dynTree); fi; fi; fi; end;
ApplySuffixTreeExtension := function(where, pattern, i, j)
local currentNode, currentEdge, location, label, newNode,
nextChar, family, retval, termEdge, justMarked;
if IsList(where) then
currentEdge := where[1];
location := where[2];
label := LabelOfSuffixTreeEdge(currentEdge); if label[location+1] <> nextChar then
family := FamilyObj(currentEdge); # Have to add a new internal node and external node
currentNode := CreateInternalSuffixTreeNode(family, pattern, j, i);
AddInternalSuffixTreeNode(currentEdge, location, currentNode);
Info( InfoDynamicDictionary, 1, "Added new internal node with edge label ",
LabelOfSuffixTreeEdge(currentEdge) );
newNode := CreateExternalSuffixTreeNode(family, pattern, j);
AddExternalSuffixTreeNode(currentNode, newNode);
Info( InfoDynamicDictionary, 1, "Added new external node with label ",
LabelOfSuffixTreeNode(newNode) );
retval.internal := true; if nextChar = [] then
termEdge := SuffixTreeEdgeStartingAt(currentNode, []); if ForAny(termEdge!.child!.label, x -> x[2] = 1) then
currentNode!.marked := true;
Info(InfoDynamicDictionary, 1, "Marked node: ",
LabelOfSuffixTreeNode(currentNode));
justMarked := true; fi; fi;
InsertIntoDynamicForest(currentNode);
InsertIntoDynamicForest(newNode); else
currentNode := currentEdge!.parent; if location+1 < Length(label) then
retval.currentEdge := currentEdge;
retval.location := location+1;
retval.nextNode := currentNode; else
retval.nextNode := currentEdge!.child; fi; fi; else
currentNode := where;
currentEdge := SuffixTreeEdgeStartingAt(currentNode, nextChar); if currentEdge = fail then # Have to add a new external node
Assert(1, not IsExternalSuffixTreeNode(currentNode), "Trying to extend an external node!");
family := FamilyObj(currentNode);
newNode := CreateExternalSuffixTreeNode(family, pattern, j);
AddExternalSuffixTreeNode(currentNode, newNode);
Info( InfoDynamicDictionary, 1, "Added new external node with label ",
LabelOfSuffixTreeNode(newNode) );
retval.nextNode := currentNode;
InsertIntoDynamicForest(newNode); else if Length(LabelOfSuffixTreeEdge(currentEdge)) > 1then
retval.currentEdge := currentEdge;
retval.location := 1;
retval.nextNode := currentNode; else
retval.nextNode := currentEdge!.child; fi; fi; fi;
if nextChar = [] and newNode = 0then
Assert(1, IsExternalSuffixTreeNode(currentEdge!.child), "Match of terminating character not at leaf!");
Add(currentEdge!.child!.label, [pattern, j]); # Mark an old node if j = 1 and
Length(LabelOfSuffixTreeNode(currentEdge!.parent)) = i then
currentEdge!.parent!.marked := true;
Info(InfoDynamicDictionary, 1, "Marked node: ",
LabelOfSuffixTreeNode(currentEdge!.parent));
InsertIntoDynamicForest(currentEdge!.parent); fi; # also, fake as if we added a new leaf so the phase doesn't # prematurely end.
newNode := currentEdge!.child; fi;
i := 0;
currentNode := suffixTree!.root;
nextNode := currentNode; while i < m-1do
location := 0;
currentEdge := SuffixTreeEdgeStartingAt(currentNode, pattern[i+1]); if currentEdge <> fail then
label := LabelOfSuffixTreeEdge(currentEdge);
nextNode := currentEdge!.child; if i < m then
i := i + 1;
location := 1; fi; else # failed to match on any of the children, so get out
break; fi;
# move as far as we can down the edge while location < Length(label) and i < m-1
and pattern[i+1] = label[location+1] do
i := i + 1;
location := location + 1;
od;
# If we finished matching the current label, move on to the next # node. Note that we do not need to check if this is an internal # or external node since external edges have the terminating # symbol. if location = Length(label) then
currentNode := nextNode;
location := 0; else # we ended in the middle of an edge so break out.
break; fi;
od;
Info( InfoDynamicDictionary, 1, "Matched ", i, " items.");
j_i := 0; while i < m do
phaseDone := false;
j := j_i+1;
Info( InfoDynamicDictionary, 1, "Begin phase ", i, " extension ", j );
Info( InfoDynamicDictionary, 1, "Current node: ", LabelOfSuffixTreeNode(currentNode) ); if currentEdge <> fail then
Info( InfoDynamicDictionary, 1, "Current edge: ", LabelOfSuffixTreeEdge(currentEdge) );
Info( InfoDynamicDictionary, 1, "Location: ", location ); fi; if location <> 0then
extInfo := ApplySuffixTreeExtension([currentEdge, location],
newPattern, i, j); else
extInfo := ApplySuffixTreeExtension(currentNode,
newPattern, i, j); fi; if extInfo.internal then
w := extInfo.currentNode; else
w := 0; fi;
v := extInfo.currentNode; if extInfo.newNode = 0then
j_i := j - 1;
currentNode := extInfo.nextNode;
currentEdge := extInfo.currentEdge;
location := extInfo.location;
phaseDone := true; else # increment j_i since we added a new leaf
j_i := j_i + 1;
currentNode := suffixTree!.root;
location := 0; fi;
j := j + 1; while j <= i+1 and not phaseDone do
Info( InfoDynamicDictionary, 1, "Begin phase ", i, " extension ", j );
Info( InfoDynamicDictionary, 1, "Current node: ", LabelOfSuffixTreeNode(currentNode) ); if currentEdge <> fail then
Info( InfoDynamicDictionary, 1, "Current edge: ",
LabelOfSuffixTreeEdge(currentEdge) );
Info( InfoDynamicDictionary, 1, "Location: ", location ); fi; # assumption, v is not the root right now if v!.suffixLink = 0 and v <> suffixTree!.root then
label := LabelOfSuffixTreeEdge(v!.parentEdge);
v := v!.parentEdge!.parent; else
label := []; fi; if v <> suffixTree!.root then
currentNode := v!.suffixLink; else
label := pattern{[j..i]};
currentNode := v; fi;
g := Length(label);
h := 1;
location := 0;
while g > 0do
currentEdge := SuffixTreeEdgeStartingAt(currentNode, label[h]);
g1 := Length(LabelOfSuffixTreeEdge(currentEdge)); if g1 < g then
h := h + g1;
currentNode := currentEdge!.child; elif g = g1 then
currentNode := currentEdge!.child;
nextNode := currentNode;
location := 0; else
nextNode := currentEdge!.child;
location := g; fi;
g := g - g1;
od; if location <> 0then
extInfo := ApplySuffixTreeExtension([currentEdge, location],
newPattern, i, j); else
extInfo := ApplySuffixTreeExtension(currentNode,
newPattern, i, j); fi; if extInfo.internal then
x := extInfo.currentNode; else
x := 0; fi;
v := extInfo.currentNode; if extInfo.newNode = 0then
j_i := j - 1;
currentNode := extInfo.nextNode;
currentEdge := extInfo.currentEdge;
location := extInfo.location;
phaseDone := true; else # increment j_i since we added a new leaf
j_i := j_i + 1;
currentNode := suffixTree!.root;
location := 0; fi; if w <> 0then
Assert(1, LabelOfSuffixTreeNode(v) = pattern{[j..i]}, "Incorrectly setting suffix link!");
w!.suffixLink := v; fi;
w := x;
j := j + 1;
od;
i := i+1;
od;
Add(suffixTree!.patterns, newPattern);
return Length(suffixTree!.patterns); end );
DeleteFromDynamicForest := function(u, deleted, q)
local v;
v := ParentNode(u);
if IsExternalSuffixTreeNode(u) then
CutDynamicTree(u!.dynTree); elif deleted then
CutDynamicTree(u!.dynTree);
CutDynamicTree(q!.dynTree);
LinkDynamicTrees(q!.dynTree, v!.dynTree); else
LinkDynamicTrees(u!.dynTree, v!.dynTree); fi; end;
InstallMethod( DeletePatternFromSuffixTree, "for suffix trees and positive integers",
true,
[IsSuffixTree and IsDefaultSuffixTreeRep, IsPosInt], 0, function( st, patternNum )
local currentNode, currentEdge, nextNode, location, pos,
g, g1, h, pattern, label, i, m, u, v, w, children,
parent, n;
pattern := st!.patterns[patternNum];
currentNode := st!.root;
label := pattern[2];
m := Length(label);
for i in [1..m] do
g := Length(label);
h := 1;
location := 0;
while g > 0do
currentEdge := SuffixTreeEdgeStartingAt(currentNode, label[h]);
g1 := Length(LabelOfSuffixTreeEdge(currentEdge)); if g1 < g then
h := h + g1;
currentNode := currentEdge!.child; elif g = g1 then
currentNode := currentEdge!.child;
nextNode := currentNode;
location := 0; else
nextNode := currentEdge!.child;
location := g; fi;
g := g - g1;
od;
u := currentNode;
v := ParentNode(u);
children := Sum(v!.edges, function(x) if IsExternalSuffixTreeNode(x!.child) then
return Length(x!.child!.label); else
return 1; fi; end ); if v = st!.root then
Assert(1, IsExternalSuffixTreeNode(u), "$u$ should be an external node!");
Info(InfoDynamicDictionary, 1, "Deleting node $u$: ",
LabelOfSuffixTreeNode(u));
Info(InfoDynamicDictionary, 1, "Length of $u$ label: ", Length(u!.label)); if Length(u!.label) > 1then
u!.label := Filtered(u!.label, x -> x[1][1] <> patternNum); else
DeleteFromDynamicForest(u, true, 0);
v!.edges := Filtered(v!.edges, x -> x <> u!.parentEdge);
u!.parentEdge!.parent := 0;
u!.parentEdge!.child := 0; fi; if i = 1
and LabelOfSuffixTreeEdge(u!.parentEdge) = [[]]
and v!.marked then
Info(InfoDynamicDictionary, 1, "Unmarked: ", LabelOfSuffixTreeNode(v));
v!.marked := false;
DeleteFromDynamicForest(v, false, 0); fi; elif children > 2then
Assert(1, IsExternalSuffixTreeNode(u), "$u$ should be an external node!");
Info(InfoDynamicDictionary, 1, "Deleting node $u$: ",
LabelOfSuffixTreeNode(u));
Info(InfoDynamicDictionary, 1, "Length of $u$ label: ", Length(u!.label)); if Length(u!.label) > 1then
u!.label := Filtered(u!.label, x -> x[1][1] <> patternNum); else
DeleteFromDynamicForest(u, true, 0);
v!.edges := Filtered(v!.edges, x -> x <> u!.parentEdge);
u!.parentEdge!.parent := 0;
u!.parentEdge!.child := 0; fi; if i = 1
and LabelOfSuffixTreeEdge(u!.parentEdge) = [[]]
and v!.marked then
Info(InfoDynamicDictionary, 1, "Unmarked: ", LabelOfSuffixTreeNode(v));
v!.marked := false;
DeleteFromDynamicForest(v, false, 0); fi; else
Assert(1, IsExternalSuffixTreeNode(u), "$u$ should be an external node!");
Info(InfoDynamicDictionary, 1, "Deleting node $u$: ",
LabelOfSuffixTreeNode(u));
Info(InfoDynamicDictionary, 1, "Length of $u$ label: ", Length(u!.label)); if Length(u!.label) > 1then
u!.label := Filtered(u!.label, x -> x[1][1] <> patternNum); else
DeleteFromDynamicForest(u, true, 0);
v!.edges := Filtered(v!.edges, x -> x <> u!.parentEdge);
u!.parentEdge!.parent := 0;
u!.parentEdge!.child := 0; fi; if i = 1
and LabelOfSuffixTreeEdge(u!.parentEdge) = [[]]
and v!.marked then
Info(InfoDynamicDictionary, 1, "Unmarked: ", LabelOfSuffixTreeNode(v));
v!.marked := false;
DeleteFromDynamicForest(v, false, 0); fi;
Assert(1, Length(v!.edges) = 1, "$v$ is only supposed to have one child!");
Info(InfoDynamicDictionary, 1, "Deleting node $v$: ",
LabelOfSuffixTreeNode(v));
w := v!.edges[1]!.child;
DeleteFromDynamicForest(v, true, w);
parent := ParentNode(v);
n := Length(LabelOfSuffixTreeEdge(v!.parentEdge));
v!.parentEdge!.label := w!.parentEdge!.label;
v!.parentEdge!.label[2] := v!.parentEdge!.label[2] - n;
v!.parentEdge!.child := w;
w!.parentEdge := v!.parentEdge;
v!.parentEdge := 0;
Info(InfoDynamicDictionary, 1, "Deleted edge, new label is",
LabelOfSuffixTreeEdge(w!.parentEdge) ); fi; if i < m then if v = st!.root then
currentNode := v;
label := label{[2..Length(label)]}; else
currentNode := v!.suffixLink;
label := LabelOfSuffixTreeEdge(u!.parentEdge); fi; fi;
od; end );
InstallMethod( AllPatternsInSequence, "for suffix trees and lists",
true,
[IsSuffixTree and IsDefaultSuffixTreeRep, IsList], 0, function( st, s )
local clocus, elocus, alpha, beta, beta_h, j, k, n, x, y, u, v,
occ, currentEdge, lastNode, currentLabel, location;
n := Length(s);
occ := [];
clocus := st!.root;
beta := [];
k := 1;
for j in [1..n] do if clocus <> st!.root then
x := clocus!.suffixLink;
beta_h := beta;
alpha := []; while Length(alpha) < Length(beta_h) do
beta_h := beta_h{[Length(alpha)+1..Length(beta_h)]};
currentEdge := SuffixTreeEdgeStartingAt(x, beta_h[1]);
Assert(1, currentEdge <> fail, "Failed to find a guaranteed path!");
alpha := LabelOfSuffixTreeEdge(currentEdge); if Length(alpha) < Length(beta_h) then
x := currentEdge!.child; fi;
od; if Length(alpha) > Length(beta_h) then
clocus := x;
beta := beta_h; else if alpha = [] then
y := x; else
y := currentEdge!.child; fi;
lastNode := y;
k := j + Length(LabelOfSuffixTreeNode(y)); if k <= Length(s) then
currentEdge := SuffixTreeEdgeStartingAt(y, s[k]); else
currentEdge := fail; fi; while currentEdge <> fail do
y := currentEdge!.child;
location := 2;
k := k + 1;
currentLabel := LabelOfSuffixTreeEdge(currentEdge); while location <= Length(currentLabel) and k <= Length(s) do if currentLabel[location] = s[k] then
k := k + 1;
location := location + 1; else
break; fi;
od; if location > Length(currentLabel) then
lastNode := y; if k <= Length(s) then
currentEdge := SuffixTreeEdgeStartingAt(y, s[k]); else
currentEdge := fail; fi; else
currentEdge := fail; fi;
od;
clocus := lastNode; if j+Length(LabelOfSuffixTreeNode(clocus)) <= Length(s) then
beta := s{[j+Length(LabelOfSuffixTreeNode(clocus))..k-1]}; else
beta := []; fi; fi; else
y := st!.root;
beta_h := beta{[2..Length(beta)]};
lastNode := y;
k := j + Length(LabelOfSuffixTreeNode(y)); if k <= Length(s) then
currentEdge := SuffixTreeEdgeStartingAt(y, s[k]); else
currentEdge := fail; fi; while currentEdge <> fail do
y := currentEdge!.child;
location := 2;
k := k + 1;
currentLabel := LabelOfSuffixTreeEdge(currentEdge); while location <= Length(currentLabel) and k <= Length(s) do if currentLabel[location] = s[k] then
k := k + 1;
location := location + 1; else
break; fi;
od; if location > Length(currentLabel) then
lastNode := y; if k <= Length(s) then
currentEdge := SuffixTreeEdgeStartingAt(y, s[k]); else
currentEdge := fail; fi; else
currentEdge := fail; fi;
od;
clocus := lastNode; if j+Length(LabelOfSuffixTreeNode(clocus)) <= Length(s) then
beta := s{[j+Length(LabelOfSuffixTreeNode(clocus))..k-1]}; else
beta := []; fi; fi;
Info(InfoDynamicDictionary, 1, "Label of clocus: ",
LabelOfSuffixTreeNode(clocus));
Info(InfoDynamicDictionary, 1, "Beta: ", beta); if not IsEmpty(beta) then
currentEdge := SuffixTreeEdgeStartingAt(clocus, beta[1]); if currentEdge <> fail then
elocus := currentEdge!.child; if IsExternalSuffixTreeNode(elocus)
and Length(LabelOfSuffixTreeEdge(currentEdge)) = Length(beta)+1 then
Append(occ, List(Filtered(elocus!.label, z -> z[2] = 1),
t -> [t[1][1], j])); fi; fi; fi;
u := clocus; while u <> st!.root do
v := RootOfDynamicTree(u!.dynTree)!.item; if v <> st!.root then
currentEdge := SuffixTreeEdgeStartingAt(v, []);
elocus := currentEdge!.child;
Append(occ, List(Filtered(elocus!.label, z -> z[2] = 1),
t -> [t[1][1], j]));
u := ParentNode(v); else
u := st!.root; fi;
od;
od;
return occ; end );
InstallMethod( SequenceInPatterns, "for suffix trees and lists",
true,
[IsSuffixTree and IsDefaultSuffixTreeRep, IsList], 0, function( st, seq )
local currentNode, currentEdge, i, m, n, location,
currentLabel, occ, InOrder;
occ := [];
currentNode := st!.root;
m := Length(seq);
i := 0;
location := 0; while i < m do if location = 0then
currentEdge := SuffixTreeEdgeStartingAt(currentNode, seq[i+1]); if currentEdge = fail then
break; fi;
location := 1;
currentLabel := LabelOfSuffixTreeEdge(currentEdge);
n := Length(currentLabel); elif seq[i+1] = currentLabel[location+1] then
location := location + 1; else
break; fi; if location >= n then
currentNode := currentEdge!.child;
location := 0; fi;
i := i + 1;
od;
if i = m then if location <> 0then
currentNode := currentEdge!.child; fi;
InOrder := function(node)
local edge;
if IsExternalSuffixTreeNode(node) then
Append(occ, List(node!.label, x -> [x[1][1], x[2]])); else for edge in node!.edges do
InOrder(edge!.child);
od; fi; end;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.