void SuffixTree::build(const std::string &str) { sTString = str; for(auto &v: sTVertices) { delete v; } sTVertices.clear(); size_t lastGoodOperation = 1; sTVertices.push_back(new Vertex()); // Build tree sTRoot = *sTVertices.begin(); // that content root sTRoot->setSuffixLink(sTRoot); // and vertex for first character. sTRoot->setMark(0); // Field mark for vertex is position of begining in the string for lists sTVertices.push_back(new Vertex()); // and length for the root for inner vertices. sTRoot->addEdgeTo(*(--sTVertices.end()), 0, INF(), &sTCurrentStageValue, sTString[0]); (*(--sTVertices.end()))->setMark(0); for(size_t i = 1, size = str.size() + 1; i < size; ++i) { ++sTCurrentStageValue; Edge e; Vertex *lastVertex = sTRoot; for(size_t j = lastGoodOperation; j < i + 1; ++j) { size_t path = 0; Vertex *currentVertex; if(lastVertex->hasSuffixLink()) { currentVertex = lastVertex->suffixLink(); // If vertex hasn't suffix link that } else { // parent must have the suffix link. currentVertex = lastVertex->parent()->suffixLink(); } path = currentVertex->mark(); while(j + path < i) { e = currentVertex->edgeForCharacter(str[j + path]); path += e.length(); currentVertex = e.vertexTwo(); } if(j + path != i) { path -= e.length(); currentVertex = e.vertexOne(); } if(currentVertex->isList()) { if(!lastVertex->hasSuffixLink()) { // If is list, that the second value of edge must change automatically, lastVertex->setSuffixLink(currentVertex->parent()); // so we only set the suffix link. } lastVertex = currentVertex->parent(); } else if(!currentVertex->hasEdgeForCharacter(sTString[j + path])) { sTVertices.push_back(new Vertex()); Vertex *newVertex = *(--sTVertices.end()); newVertex->setMark(j); currentVertex->addEdgeTo(newVertex, i, INF(), &sTCurrentStageValue, sTString[i]); if(!lastVertex->hasSuffixLink()) { lastVertex->setSuffixLink(currentVertex); } lastVertex = currentVertex; lastGoodOperation = j + 1; } else if(j + path == i || str[e.firstValue() + i - j - path] == str[i]) { // If tree already has the current substring, if(!lastVertex->hasSuffixLink()) { // we only set the suffix link, lastVertex->setSuffixLink(currentVertex); // and we can break appendin of strings in tree. } lastVertex = currentVertex; lastGoodOperation = j; break; } else { // Another variant if end of substring without last character e = currentVertex->edgeForCharacter(sTString[j + path]); // lies in the middle of the edge. sTVertices.push_back(new Vertex()); Vertex *splitVertex = *(--sTVertices.end()); currentVertex->deleteEdgeForCharacter(sTString[e.firstValue()]); splitVertex->addEdgeTo(e.vertexTwo(), e.firstValue() + i - j - path, e.secondValue(), &sTCurrentStageValue, sTString[e.firstValue() + i - j - path]); currentVertex->addEdgeTo(splitVertex, e.firstValue(), e.firstValue() + i - j - 1 - path, &sTCurrentStageValue, sTString[e.firstValue()]); splitVertex->setMark(splitVertex->parent()->mark() + i - j - path); sTVertices.push_back(new Vertex()); Vertex *newVertex = *(--sTVertices.end()); newVertex->setMark(j); splitVertex->addEdgeTo(newVertex, i, INF(), &sTCurrentStageValue, sTString[i]); if(!lastVertex->hasSuffixLink()) { lastVertex->setSuffixLink(splitVertex); } lastVertex = splitVertex; lastGoodOperation = j + 1; } } } }