void correctMerge(unsigned int v, unsigned int parentsPlace, SuffixTree &merged, IndexedPair<MergeTreesStruct> &updatedTrees, const vector <unsigned int> &trueLength, const vector <int> &input, unsigned int copyTree ) { if (merged[v].isHiddenInfo()) { doSomething(updatedTrees, [&merged, &v] (MergeTreesStruct &tree) { tree.evaluate(merged, v); }); if (copyTree == 2 && merged[v].depth != trueLength[v]) { unsigned int commonLength = trueLength[v] - merged[merged[v].parent].depth; MergeTreesStruct& donor = minimal(updatedTrees, [&input, &commonLength] (MergeTreesStruct &tree) -> int { auto const &node = tree.tree[tree.info]; return input[tree.suffix[tree.info] + (node.parent == -1 ? 0 : tree.tree[node.parent].depth) + commonLength]; } ); copyTree = donor.number; copyNodeExceptParentAndChildren(donor.tree[donor.info], merged[v]); unsigned int newNodeIndex = merged.splitEdge(merged[v].parent, parentsPlace, commonLength ); unsigned int newCopy = merged.newNode(newNodeIndex); merged[newNodeIndex].push_back(newCopy); MergeTreesStruct ¬Donor = *xorPointers(&donor, &updatedTrees[0], &updatedTrees[1] ); copyNodeExceptParentAndChildren(notDonor.tree[notDonor.info], merged[newCopy] ); merged[newCopy].indexOfParentEdge += commonLength; copySubTree(notDonor.tree, merged, notDonor.info, newCopy); } else { MergeTreesStruct &donor = minimal(updatedTrees, [©Tree] (MergeTreesStruct &tree) -> pair<bool, bool> { return make_pair(copyTree == 2 || copyTree != tree.number, !(tree.tree[tree.info].leaf != -1) ); } ); copyNodeExceptParentAndChildren(donor.tree[donor.info], merged[v]); } } if (copyTree != 2 && merged[v].leaf != -1 && merged[v].leaf % 2 != copyTree) { merged[v].leaf = -1; } for (unsigned int i = 0; i < merged[v].size(); ++i) { unsigned int u = merged[v][i]; correctMerge(u, i, merged, updatedTrees, trueLength, input, copyTree); } }
SuffixTree buildSuffixTreeFromSA(vector <unsigned int> &sa, vector <unsigned int> &lcp, unsigned int length ) { vector <int> tmp; SuffixTree result = buildTempSuffixTree(tmp); int newNodeIndex = result.newNode(result.root, sa[0], length - sa[0], sa[0]); result[result.root].push_back(newNodeIndex); unsigned int current = newNodeIndex; for (unsigned int i = 1; i < sa.size(); ++i) { while (result[current].parent != -1 && result[result[current].parent].depth >= lcp[i - 1] ) { current = result[current].parent; } unsigned int parent; if (result[current].parent != -1 && result[result[current].parent].depth == lcp[i - 1] ) { parent = result[current].parent; } else if (result[current].depth == lcp[i - 1]) { parent = current; } else { unsigned int currentParent = result[current].parent; parent = result.splitEdge(currentParent, result[currentParent].size() - 1, lcp[i - 1] - result[currentParent].depth ); result[parent].leaf = (length - sa[i] == lcp[i - 1] ? sa[i] : -1); } if (lcp[i - 1] != length - sa[i]) { newNodeIndex = result.newNode(parent, sa[i] + lcp[i - 1], length - sa[i], sa[i] ); result[parent].push_back(newNodeIndex); parent = newNodeIndex; } current = parent; } return result; }
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; }