return false;
}
-static bool node_edge_present_2(const struct node *self, uint8_t edge, size_t len, const uint8_t *str, size_t i)
+static bool node_edge_next_present(const struct node *self, size_t len, const uint8_t *str, size_t i)
{
- const struct node *node;
-
- for (node = self->son; node; node = node->brother)
- if (str[node->from] == edge)
- return str[node->from+len] == str[i];
- return false;
+ return str[self->from+len] == str[i];
}
-static bool node_edge_end(const struct node *self, uint8_t edge, size_t len, const uint8_t *str)
+static bool node_edge_end(const struct node *self, size_t len)
{
- const struct node *node;
-
- for (node = self->son; node; node = node->brother)
- if (str[node->from] == edge)
- return node->from + len >= node->to;
-
- return false;
+ return self && self->from + len >= self->to;
}
static struct node *node_edge(struct node *self, uint8_t edge, const uint8_t *str)
struct node *root;
struct node *prev;
struct node *active_node;
- uint8_t active_edge = '^';
+ struct node *active_edge = (struct node *) 0;
size_t active_len = 0;
size_t rem = 0;
size_t i;
cont = false;
while (rem > 0 && !cont) {
if (active_len == 0) {
- if (!node_edge_present(active_node, in, i)) {
+ if (node_edge_present(active_node, in, i))
+ cont = true;
+ else {
node_init(nodes + n, i);
node_add_son(active_node, nodes + n);
++n;
--rem;
- if (active_node != root) {
- active_node = active_node->link ? active_node->link : root;
- if (active_node == root) {
- active_len = rem - 1;
- active_edge = in[i-active_len];
- }
- }
- } else {
- active_edge = in[i];
- ++active_len;
- cont = true;
}
} else if (active_len > 0) {
- if (!node_edge_present_2(active_node, active_edge, active_len, in, i)) {
+ if (node_edge_next_present(active_edge, active_len, in, i))
+ cont = true;
+ else {
node_init(nodes + n + 1, i);
- node_split_son(active_node, active_edge, active_len, nodes + n, nodes + n + 1, in);
- if (prev) {
- prev->link = nodes + n;
- }
+ node_split_son(active_node, in[active_edge->from], active_len, nodes + n, nodes + n + 1, in);
+ if (prev) prev->link = nodes + n;
prev = nodes + n;
n += 2;
--rem;
if (active_node == root) {
--active_len;
- active_edge = in[i-active_len];
- } else {
- active_node = active_node->link ? active_node->link : root;
- if (active_node == root) {
- active_len = rem - 1;
- active_edge = in[i-active_len];
- }
}
- } else {
- ++active_len;
- cont = true;
}
}
- while (node_edge_end(active_node, active_edge, active_len, in)) {
- active_node = node_edge(active_node, active_edge, in);
+ if (!cont && active_node != root) {
+ active_node = active_node->link ? active_node->link : (active_len = rem - 1, root);
+ }
+ active_edge = node_edge(active_node, in[i-active_len], in);
+ if (cont) ++active_len;
+ while (node_edge_end(active_edge, active_len)) {
+ active_node = active_edge;
active_len -= active_node->to - active_node->from;
- active_edge = in[i-active_len];
+ active_edge = node_edge(active_node, in[i-active_len], in);
}
}
}