int cleanTreeDfs(unsigned int v, unsigned int parent, SuffixTree &tree) { int leaf = tree[v].leaf; for (unsigned int i = 0; i < tree[v].size(); ++i) { unsigned int u = tree[v][i]; int newLeaf = cleanTreeDfs(u, i, tree); if (leaf == -1) { leaf = newLeaf; } } unsigned int freeCell = 0; for (unsigned int i = 0; i < tree[v].size(); ++i) { if (tree[v][i] != -1) { tree[v][freeCell] = tree[v][i]; ++freeCell; } } tree[v].resize(freeCell); if (tree[v].size() <= 1 && tree[v].leaf == -1 && v != tree.root) { tree.deleteUselessNode(v, parent, leaf); } return leaf; }
int decompressDfs(unsigned int v, unsigned int inParentIndex, SuffixTree &tree, const vector <int> &input, unsigned int depth ) { int leaf = -1; unsigned int oldDepth = tree[v].depth; tree[v].depth = depth; for (unsigned int i = 0; i < tree[v].size(); ++i) { unsigned int u = tree[v][i]; int newLeaf = decompressDfs(u, i, tree, input, depth + tree[u].lengthOfEdge(tree, oldDepth) * 2 - (tree[u].lastIndex(tree, oldDepth) == input.size() / 2 + 1) ); if (leaf == -1) { leaf = newLeaf; } } tree[v].indexOfParentEdge *= 2; if (tree[v].leaf != -1) { tree[v].leaf = min(tree[v].leaf * 2, static_cast<int>(input.size())); } vector <unsigned int> myNewChildren; if (tree[v].size()) { vector <unsigned int> similarKids; unsigned int firstKidIndex = 0; similarKids.push_back(tree[v][0]); for (unsigned int i = 1; i <= tree[v].size(); ++i) { if (i != tree[v].size()) { unsigned int current = tree[v][i]; unsigned int previous = tree[v][i - 1]; while (i < tree[v].size() && input[tree[current].indexOfParentEdge] == input[tree[previous].indexOfParentEdge] ) { similarKids.push_back(current); ++i; previous = current; if (i != tree[v].size()) { current = tree[v][i]; } } } if (similarKids.size() != 1) { unsigned int newNodeIndex = tree.splitEdge(v, firstKidIndex, 1); auto &newNode = tree[newNodeIndex]; for (unsigned int j = 1; j < similarKids.size(); ++j) { auto ¤tChild = tree[similarKids[j]]; currentChild.parent = newNodeIndex; ++currentChild.indexOfParentEdge; newNode.push_back(similarKids[j]); } if (newNode.size() && tree[newNode[0]].lengthOfEdge(tree) == 0 ) { newNode.leaf = tree[newNode[0]].leaf; tree.deleteUselessNode(newNode[0], 0, newNode.leaf); newNode.deleteFirstChild(); } myNewChildren.push_back(newNodeIndex); tree.checkNode(tree[newNodeIndex]); } else { myNewChildren.push_back(similarKids.back()); } if (i != tree[v].size()) { similarKids.clear(); similarKids.push_back(tree[v][i]); firstKidIndex = i; } } } tree[v].renewChildren(myNewChildren); if (tree[v].size() == 1 && v != tree.root && tree[v].leaf == -1) { tree.deleteUselessNode(v, inParentIndex, leaf); } if (tree[v].leaf != -1) { leaf = tree[v].leaf; } return leaf; }