SuffixTree buildTempSuffixTree(const vector <int> &input) { if (input.size() == 0) { return SuffixTree(); } if (input.size() == 1) { SuffixTree result; unsigned int newNodeIndex = result.newNode(result.root, 0, 1, 0); result[result.root].push_back(newNodeIndex); return result; } SuffixTree compressed = buildTempSuffixTree(compressInput(input)); decompress(compressed, input); SuffixTree &even = compressed; checkTree("EVEN:\n", even, input); SuffixTree odd = buildOddSuffixTree(even, input); checkTree("ODD:\n", odd, input); SuffixTree almostResult = mergeTrees(even, odd, input); checkTree("ALMOST:\n", almostResult, input); cleanTreeDfs(almostResult.root, -1, almostResult); checkTree("RESL:\n", almostResult, input); return almostResult; }
unsigned int appendCopyNode(const SuffixTree &from, SuffixTree &to, unsigned int toStart, unsigned int u ) { unsigned int newStart = to.newNode(toStart); to[toStart].push_back(newStart); copyNodeExceptParentAndChildren(from[u], to[newStart]); copySubTree(from, to, u, newStart); return newStart; }
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; }
void mergeNodes(unsigned int first, unsigned int second, unsigned int to, SuffixTree &result, SuffixTree &tree1, SuffixTree &tree2, const vector <int> &input ) { IndexedPair<MergeNodesStruct> merging(MergeNodesStruct(tree1, first, input), MergeNodesStruct(tree2, second, input) ); while (!merging[0].end() && !merging[1].end()) { doSomething(merging, [] (MergeNodesStruct &instance) { instance.evaluate(); }); if (merging[0].symbol == merging[1].symbol) { doSomething(merging, [] (MergeNodesStruct &instance) { instance.length = instance.tree[instance.child].lengthOfEdge(instance.tree); }); unsigned int minimalLength = min(merging[0].length, merging[1].length); if (merging[0].length != merging[1].length) { MergeNodesStruct &splitVictim = minimal(merging, [] (const MergeNodesStruct &instance) -> int { return -static_cast<int>(instance.length); } ); splitVictim.split(minimalLength); } unsigned int newNodeIndex = result.newNode(to); auto &newNode = result[newNodeIndex]; result[to].push_back(newNodeIndex); if (minimalLength == 1) { MergeNodesStruct &recipient = minimal(merging, [] (const MergeNodesStruct &instance) -> pair<unsigned int, int> { return make_pair(instance.length, -instance.tree[instance.child].leaf); } ); copyNodeExceptParentAndChildren(recipient.tree[recipient.child], newNode ); } else { newNode.setHiddenInfo(merging[0].child, merging[1].child); newNode.depth = minimalLength + result[to].depth; } mergeNodes(merging[0].child, merging[1].child, newNodeIndex, result, tree1, tree2, input); doSomething(merging, [] (MergeNodesStruct &instance) { ++instance.childIndex; }); } else { MergeNodesStruct &recipient = minimal(merging, [] (const MergeNodesStruct &instance) -> int { return instance.symbol; } ); ++recipient.childIndex; appendCopyNode(recipient.tree, result, to, recipient.child); } } MergeNodesStruct &recipient = minimal(merging, [] (const MergeNodesStruct & instance) -> bool { return instance.end(); } ); for (; !recipient.end(); ++recipient.childIndex) { recipient.evaluate(); appendCopyNode(recipient.tree, result, to, recipient.child); } }