self->son = split;
}
+static void node_sort_sons(struct node *self)
+{
+ struct node *node, *brother, *tmp;
+
+ for (brother = (struct node *) 0, node = self->son; node && node->brother; brother = node, node = node->brother) {
+ if (node->to > node->brother->to) {
+ if (brother) {
+ tmp = node->brother;
+ node->brother = node->brother->brother;
+ tmp->brother = node;
+ brother->brother = tmp;
+ } else {
+ tmp = node->brother;
+ node->brother = node->brother->brother;
+ tmp->brother = node;
+ self->son = tmp;
+ }
+ brother = (struct node *) 0;
+ node = self->son;
+ }
+ }
+}
+
static struct node *node_edge_inv(struct node *self, uint8_t edge, const uint8_t *str, struct node **brother, bool seen[], uint8_t *code, bool record_seen)
{
struct node *node;
if (record_seen) {
- for (node = self->son; node; node = node->brother) {
+ node_sort_sons(self);
+
+ for (*brother = (struct node *) 0, node = self->son; node; *brother = node, node = node->brother) {
if (!seen[str[node->from]]) {
seen[str[node->from]] = true;
- if (*code == 0) {
- edge = str[node->from];
- break;
- }
+ if (*code == 0) return node;
--*code;
}
}
- if (!node) {
- return (struct node *) 0;
- }
+ } else {
+ for (*brother = (struct node *) 0, node = self->son; node; *brother = node, node = node->brother)
+ if (str[node->from] == edge)
+ return node;
}
- for (*brother = (struct node *) 0, node = self->son; node; *brother = node, node = node->brother)
- if (str[node->from] == edge)
- return node;
-
return (struct node *) 0;
}
struct node *node;
if (record_seen) {
- for (node = self->son; node; node = node->brother) {
- if (str[node->from] == edge)
- break;
+ node_sort_sons(self);
+
+ for (*brother = (struct node *) 0, node = self->son; node; *brother = node, node = node->brother) {
+ if (str[node->from] == edge) return node;
if (!seen[str[node->from]]) {
seen[str[node->from]] = true;
++*code;
}
}
+ } else {
+ for (*brother = (struct node *) 0, node = self->son; node; *brother = node, node = node->brother)
+ if (str[node->from] == edge)
+ return node;
}
- for (*brother = (struct node *) 0, node = self->son; node; *brother = node, node = node->brother)
- if (str[node->from] == edge)
- return node;
-
return (struct node *) 0;
}
struct node *active_node;
struct node *active_edge = (struct node *) 0;
struct node *brother = (struct node *) 0;
- struct node *new_leaf;
size_t active_len = 0;
size_t rem = 0;
size_t i;
if (!active_edge) {
node_init(nodes + n, i);
node_add_son(active_node, nodes + n);
- new_leaf = nodes + n;
++n, --rem;
} else {
if (!seen[in[active_edge->from+active_len]]) {
if (prev) prev->link = nodes + n;
prev = nodes + n, n += 2, --rem;
if (active_node == root) --active_len;
- new_leaf = (struct node *) 0;
}
active_node = active_node->link ? active_node->link : (active_len = rem - 1, root);
- if (active_len == 0 && active_node->son == new_leaf)
+ if (active_len == 0 && active_node->son == nodes + n - 1)
brother = active_edge = (struct node *) 0;
else
- active_edge = node_edge(active_node, in[i-active_len], in, &brother, seen, &code, active_len == 0 && active_node->son != new_leaf);
+ active_edge = node_edge(active_node, in[i-active_len], in, &brother, seen, &code, active_len == 0);
}
while (active_edge && active_edge->from + active_len >= active_edge->to) {
active_node = active_edge;
struct node *active_node;
struct node *active_edge = (struct node *) 0;
struct node *brother = (struct node *) 0;
- struct node *new_leaf;
size_t active_len = 0;
size_t rem = 0;
size_t i, n;
if (!active_edge) {
node_init(nodes + n, i);
node_add_son(active_node, nodes + n);
- new_leaf = nodes + n;
++n, --rem;
} else {
if (!seen[out[active_edge->from+active_len]]) {
if (prev) prev->link = nodes + n;
prev = nodes + n, n += 2, --rem;
if (active_node == root) --active_len;
- new_leaf = (struct node *) 0;
}
active_node = active_node->link ? active_node->link : (active_len = rem - 1, root);
- if (active_len == 0 && active_node->son == new_leaf)
+ if (active_len == 0 && active_node->son == nodes + n - 1)
brother = active_edge = (struct node *) 0;
else
active_edge = node_edge_inv(active_node, out[i-active_len], out, &brother, seen, &code, active_len == 0);