unsigned long long countSubstrings(SuffixTree &tree, unsigned int v) { tree.checkNode(tree[v]); unsigned long long sum = tree[v].lengthOfEdge(tree); for (auto const &u: tree[v]) { sum += countSubstrings(tree, u); } return sum; }
void checkDfs(const SuffixTree &tree, unsigned int v, const vector<int> &input ) { #ifdef _PRINT_DBG printf("%d -> %d [label=\"", tree[v].parent, v); for (int i = tree[v].indexOfParentEdge; i != tree[v].lastIndex(tree); ++i) { printf("%d", input[i]); } printf(", %d, %d\"]\n", tree[v].leaf, tree[v].depth); #endif tree.checkNode(tree[v]); for (auto const &u: tree[v]) { checkDfs(tree, u, input); } }
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; }