Macaulay2 Engine
Loading...
Searching...
No Matches
SuffixTree.cpp
Go to the documentation of this file.
2#include <algorithm> // for copy
3#include <iterator> // for back_insert_iterator, back_inserter
4#include "NCAlgebras/Word.hpp" // for Word, operator<<
5
6void outputLabel(std::ostream& o, const Label& vec)
7{
8 o << "[";
9 for (auto i = vec.begin(); i != vec.end(); ++i)
10 {
11 if (i != vec.begin())
12 o << ",";
13 o << *i;
14 }
15 o << "]";
16}
17
18std::ostream& operator<<(std::ostream& o, const SuffixTreeNode& suffixTreeNode)
19{
20 suffixTreeNode.dump(o,0);
21 return o;
22}
23
24std::ostream& SuffixTreeNode::dump(std::ostream& o, int depth, bool dumpChildren) const
25{
26 if (mParent == nullptr)
27 {
28 // the parent is nullptr if and only if it is the root.
29 std::cout << "Root" << std::endl;
30 }
31 else
32 {
33 for (auto j = 0; j < depth; ++j) o << " ";
34 o << "Arclabel : ";
36 o << std::endl;
37
38 for (auto j = 0; j < depth; ++j) o << " ";
39 o << "Label : ";
41 o << std::endl;
42
43 for (auto j = 0; j < depth; ++j) o << " ";
44 o << "SuffixTreeLabel : ";
45 if (mSuffixLink == nullptr)
46 o << "nullptr";
47 else
48 outputLabel(o,mSuffixLink->mLabel);
49 o << std::endl;
50 }
51 if (dumpChildren)
52 {
53 for (auto pair : mChildren)
54 {
55 pair.second->dump(o,depth+1);
56 }
57 }
58 return o;
59}
60
61void outputPatterns(std::ostream& o, const SuffixTree& suffixTree)
62{
63 o << "Patterns in table: {";
64 for (auto i = suffixTree.mMonomials.begin(); i != suffixTree.mMonomials.end(); ++i)
65 {
66 if (i != suffixTree.mMonomials.begin())
67 o << ",";
68 o << Word(*i);
69 }
70 o << "}" << std::endl;
71}
72
73std::ostream& operator<<(std::ostream& o, const SuffixTree& suffixTree)
74{
75 outputPatterns(o,suffixTree);
76 suffixTree.mRoot->dump(o,0);
77 return o;
78}
80Word prefix(const Word vec, int lengthOfPrefix)
81{
82 // this command sets the pointers to the initial segment of vec
83 return Word(vec.begin(),vec.begin()+lengthOfPrefix);
84}
85
86Word suffix(const Word vec, int indexOfSuffix)
87{
88 // this command sets the pointers to the terminal segment of vec
89 return Word(vec.begin()+indexOfSuffix,vec.end());
90}
91
92bool concatenatesTo(const Word a, const Word b, const Word c)
93{
94 if (a.size() + b.size() != c.size()) return false;
95 Word tmpA(c.begin(),c.begin()+a.size());
96 Word tmpB(c.begin()+a.size(),c.end());
97 return (tmpA == a) && (tmpB == b);
98}
99
100bool isPatternPrefix(const Word a, const Word b, int startIndex)
101{
102 // here, a is a pattern label so we only compare the first a.size()-1 many entries
103 // sometimes we know that the first startIndex many symbols will match, so we start
104 // at the first possible non-match.
105 std::cout << a << " " << b << " " << startIndex << std::endl;
106 if (b.size() + 1 < a.size()) return false;
107 Word tmpA = Word(a.begin()+startIndex,a.end()-1);
108 Word tmpB = Word(b.begin()+startIndex, b.begin()+a.size()-1);
109 return (tmpA == tmpB);
110}
111
112bool isPatternPrefix(const Word a, const Word b)
113{
114 return isPatternPrefix(a,b,0);
115}
116
118{
119 SuffixTreeNode* root = new SuffixTreeNode();
120 mRoot = root;
121}
122
124{
125 for (auto i = p->childrenBegin(); i != p->childrenEnd(); ++i)
126 destroyChildren(i->second);
127 delete p;
128}
129
131{
132 // must destroy the SuffixTreeNodes owned by this object
134}
135
136auto SuffixTree::insert(const Word& w) -> size_t
137{
138 std::vector<Overlap> tmpOverlaps;
139 return insert(w,tmpOverlaps);
140}
141
142auto SuffixTree::insert(const Word& w, std::vector<Overlap>& rightOverlaps) -> size_t
143{
144 // warning: this function appends the results to the end of right overlaps.
145 int wordNum = mMonomials.size();
146 auto plList = std::vector<int> {};
147 Label tempS(w.begin(),w.end());
148 mMonomials.push_back(tempS);
149 tempS.push_back(-(wordNum + 1));
150 Word s(tempS);
151 auto v = mRoot;
152 bool isFullPattern = true;
153 while (s.size() != 0)
154 {
155 InsertType insertType;
156 if (v == mRoot) insertType = insertStepD(v,s,isFullPattern);
157 else if (v->parent() == mRoot) insertType = insertStepC(v,mRoot,suffix(Word(v->arcLabel()),1),s,isFullPattern);
158 else insertType = insertStepC(v,v->parent()->suffixLink(),Word(v->arcLabel()),s,isFullPattern);
159 auto newv = std::get<0>(insertType);
160 auto roRoot = std::get<1>(insertType);
161 auto newLocus = std::get<2>(insertType);
162 v = newv;
163 if (roRoot != nullptr)
164 {
165 plList.clear();
166 patternLeaves(roRoot,plList);
167 for(auto pl : plList)
168 {
169 auto ro0 = newLocus->getPatternNumber();
170 auto ro1 = mMonomials[ro0].size() - roRoot->label().size();
171 auto ro2 = pl;
172 rightOverlaps.push_back(std::make_tuple(ro0,ro1,ro2,true));
173 }
174 }
175 if (v != mRoot && s.size() == 2)
176 {
177 v->setSuffixLink(mRoot);
178 }
179 s = suffix(s,1);
180 isFullPattern = false;
181 }
182 return mMonomials.size();
183}
184
185auto SuffixTree::insert(std::vector<Word>& ss, std::vector<Overlap>& rightOverlaps) -> size_t
186{
187 // note that I got a crash if I used for (auto s : ss) and then inserted s.
188 // Here, s is a copy of the element in ss, not s itself, apparently?
189 // in order for it to do the right thing, I think it must be auto& s : ss
190 for (auto i = ss.begin(); i != ss.end(); ++i)
191 {
192 insert(*i,rightOverlaps);
193 }
194 return mMonomials.size();
195}
196
197auto SuffixTree::insert(Label& lab, std::vector<Overlap>& rightOverlaps) -> size_t
198{
199 Word tmpWord(lab);
200 return insert(tmpWord, rightOverlaps);
201}
202
203auto SuffixTree::insert(std::vector<Label>& labs, std::vector<Overlap>& rightOverlaps) -> size_t
204{
205 std::vector<Word> tmpWords;
206 for (auto i = labs.begin(); i != labs.end(); ++i)
207 {
208 tmpWords.push_back(Word(*i));
209 }
210 return insert(tmpWords, rightOverlaps);
211}
212
213
214// auto SuffixTree::insertWorker(SuffixTreeNode* v,
215// const Word& s,
216// bool isFullPattern) -> InsertType
217// {
218// if (v == mRoot) return insertStepD(v,s,isFullPattern);
219// if (v->parent() == mRoot) return insertStepC(v,mRoot,suffix(v->arcLabel(),1),s,isFullPattern);
220// return insertStepC(v,v->parent()->suffixLink(),v->arcLabel(),s,isFullPattern);
221// }
225 const Word& beta,
226 const Word& s,
227 bool isFullPattern) -> InsertType
228{
229 // Carries out step C in the algorithm. This amounts to computing (and building,
230 // if necessary) the suffix link of v. This function can call the Step D code
231 // as well (see the algorithm in the paper by Amir, et.al.)
232 auto iwType = extendedLocus(x, beta);
233 auto f = std::get<0>(iwType);
234 auto betaHat = std::get<1>(iwType);
235 if (f->arcLabel().size() == betaHat.size())
236 {
237 // in this case, f is in fact the locus of beta
238 v->setSuffixLink(f);
239 return insertStepD(f,suffix(s,f->label().size()),isFullPattern);
240 }
241 // in this case, f is the extended locus of beta. We need to split
242 // the arc from f to its parent and insert a node d and a child
243 // w which will be the locus of beta
244 auto d = splitArc(f,betaHat);
245 // update pattern leaf count of d
246 d->setPatternLeafCount(f->patternLeafCount());
247 d->addToPatternLeafCount(isFullPattern);
248 d->addToPatternLeafCount(f->isFullPattern());
249 // add in the locus of s
250 auto w = new SuffixTreeNode(d,suffix(s,d->label().size()),isFullPattern);
251 // set the suffix link of v to d
252 v->setSuffixLink(d);
253 if (w->label().size() == 1)
254 return std::make_tuple(d,f,w);
255 else
256 return std::make_tuple(d,nullptr,w);
257}
258
260 const Word& s,
261 bool isFullPattern) -> InsertType
262{
263 // Carries out step D in the algorithm. This amounts to constructing
264 // the locus of the head of s (which is not yet known before calling this function).
265 // find the contracted locus of s, starting from the node y
266 auto clType = contractedLocus(y,s,isFullPattern);
267 auto newy = std::get<0>(clType);
268 auto f = std::get<1>(clType);
269 auto pre = std::get<2>(clType);
270 auto tmpNode = y;
271 auto tmpLabel = s;
272
273 // drop the letters from s along the path traversed from y to std::get<0>(clType);
274 tmpLabel = suffix(tmpLabel, newy->label().size() - tmpNode->label().size());
275 tmpNode = newy;
276 if (f == nullptr)
277 {
278 // in this case, there is no common prefix of a label of any child of y and s
279 // so just create a leaf immediately.
280 auto v = new SuffixTreeNode(tmpNode,tmpLabel,isFullPattern);
281 if (tmpNode->label().size() != 0 && v->arcLabel().size() == 1)
282 return std::make_tuple(tmpNode,tmpNode,v);
283 else
284 return std::make_tuple(tmpNode,nullptr,v);
285 }
286 // in this case, f is the extended locus of s. We need to split the arc from y to f
287 auto p = splitArc(f,pre);
288 // update the patternLeafCount of p if necessary
289 p->setPatternLeafCount(f->patternLeafCount());
290 p->addToPatternLeafCount(isFullPattern);
291 p->addToPatternLeafCount(f->isFullPattern());
292 // drop common prefix
293 tmpLabel = suffix(tmpLabel,pre.size());
294 // create new leaf under p for s
295 auto w = new SuffixTreeNode (p,tmpLabel,isFullPattern);
296 // return overlap and head information
297 if (tmpLabel.size() == 1)
298 return std::make_tuple(p,p,w);
299 else
300 return std::make_tuple(p,nullptr,w);
301}
302
303// This function splits the arc from f to its parent by inserting a
304// new internal node with arc label prefix, where prefix is a prefix
305// of f->arcLabel(). A pointer to the new node is returned.
307 const Word& prefix) -> SuffixTreeNode*
308{
309 auto p = f->parent();
310 auto d = new SuffixTreeNode(p,prefix,false);
311 p->removeChild(f->arcLabel());
312 f->dropFromArcLabel(prefix.size());
313 d->addChild(f);
314 f->setParent(d);
315 return d;
316}
317
318// s is a suffix not yet in the table. This function finds the
319// locus of the longest prefix of s whose locus exists. The search
320// starts at y, and moves down the tree according to the string s.
321// The return value is the contracted locus x and a node f which is
322// either a child of y sharing a prefix pre with s - y.label, or f
323// is nullTreeNode if no such child exists.
325 const Word& s,
326 bool incrementLeafCount) const -> ContractedLocusType
327{
328 // warning: This function is not *really* const, since adding to the pattern
329 // leaf count (if incrementalLeafCount = true) could change the behavior of
330 // some functions.
331 y->addToPatternLeafCount(incrementLeafCount);
332 auto tmpNode = y;
333 auto tmpLabel = s;
334 auto match = findMatch(tmpNode,tmpLabel);
335 while (std::get<0>(match) != nullptr && std::get<1>(match) == Word(std::get<0>(match)->arcLabel()))
336 {
337 tmpNode = std::get<0>(match);
338 tmpLabel = suffix(tmpLabel,std::get<1>(match).size());
339 tmpNode->addToPatternLeafCount(incrementLeafCount);
340 match = findMatch(tmpNode,tmpLabel);
341 }
342 return std::make_tuple(tmpNode,std::get<0>(match),std::get<1>(match));
343}
344
345// For this function to work, there must be a path starting from x
346// with beta as a prefix (See e.g. Lemma 1 in Amir, et.al.) This
347// function finds the locus of the shortest word that has beta as a
348// prefix. It returns this locus, together with the prefix that
349// needs to be split (if necessary) if beta is empty, then simply
350// return (x,beta) since x is the extended locus
352 const Word& beta) const -> ExtendedLocusType
353{
354 if (beta.size() == 0) return std::make_tuple(x,beta);
355 auto tmpNode = x;
356 auto betaHat = beta;
357 auto f = std::get<0>(findMatch(tmpNode,betaHat));
358 if (f == nullptr)
359 {
360 std::cout << "Oooops" << std::endl;
361 std::cout << *tmpNode << std::endl;
362 std::cout << betaHat << std::endl;
363 }
364 while (f->arcLabel().size() < betaHat.size())
365 {
366 tmpNode = f;
367 betaHat = suffix(betaHat,f->arcLabel().size());
368 f = std::get<0>(findMatch(tmpNode,betaHat));
369 }
370 return std::make_tuple(f, betaHat);
371}
372
373// Finds an arc from y to a child whose label shares a prefix with s
374// return a std::pair of nullptrs if no match is found, i.e. the empty
375// prefix is the only shared prefix with any child of y
377 const Word& s) const -> ExtendedLocusType
378{
379 SuffixTreeNode* f = nullptr;
380 auto pre = Word();
381 for (auto i = y->childrenBegin(); i != y->childrenEnd(); ++i)
382 {
383 auto kv = *i;
384 pre = sharedPrefix(Word(kv.first),s);
385 if (pre.size() != 0)
386 {
387 f = kv.second;
388 break;
389 }
390 }
391 return std::make_pair(f,pre);
392}
393
394// Return all pattern leaves below v
395// warning: output is placed in the second argument to the function. The vector is *not*
396// cleared beforehand.
397auto SuffixTree::patternLeaves(SuffixTreeNode* v, std::vector<int>& output) const -> void
398{
399 if (v->numChildren() == 0) return;
400 for(auto x : patternLeavesWorker(v))
401 {
402 output.push_back(x->getPatternNumber());
403 }
404 return;
405}
406
407auto SuffixTree::patternLeavesWorker(SuffixTreeNode* v) const -> std::vector<SuffixTreeNode*>
408{
409 // TODO: the workers are still making a copy and returning it
410 // make change to allow for reference to be passed along.
411 // The workers also return the pointer to the node rather than the
412 // pattern number, as they probably should.
413 auto retval = std::vector<SuffixTreeNode*> {};
414 if (v->numChildren() == 0 && v->isFullPattern())
415 {
416 retval.push_back(v);
417 return retval;
418 }
419 if ((v->numChildren() == 0 && !v->isFullPattern()) || v->patternLeafCount() == 0)
420 {
421 return retval;
422 }
423 for (auto i = v->childrenBegin(); i != v->childrenEnd(); ++i)
424 {
425 auto tmp = patternLeavesWorker(i->second);
426 std::copy(tmp.begin(),tmp.end(),std::back_inserter(retval));
427 }
428 return retval;
429}
430
431// Return the longest shared prefix of s and t.
432auto SuffixTree::sharedPrefix(const Word s, const Word t) const -> Word
433{
434 int i = 0;
435 while (i < s.size() && i < t.size() && s.begin()[i] == t.begin()[i]) i++;
436 return prefix(s,i);
437}
438
439// return all leaves below v, as pointers to their nodes in the second argument
440// warning: the output vector is *not* cleared beforehand
441auto SuffixTree::allLeaves(SuffixTreeNode* v, std::vector<SuffixTreeNode*>& output) const -> void
442{
443 if (v->numChildren() == 0)
444 {
445 output.push_back(v);
446 return;
447 }
448 for (auto x = v->childrenBegin(); x != v->childrenEnd(); ++x)
449 {
450 allLeaves(x->second,output);
451 }
452 return;
453}
454
455// It is very important that the subword algorithm not perform any copies
456// of a label during the search.
457
458// functions for subwords algorithm
459auto SuffixTree::subword(const Word& w, std::pair<int,int>& output) const -> bool
460{
461 auto tmp = std::vector<std::pair<int,int>> {};
462 subwords(w,tmp,true);
463 if (tmp.size() == 0) return false;
464 else
465 {
466 std::cout << (*tmp.begin()).first << " " << (*tmp.begin()).second << std::endl;
467 output = *(tmp.begin());
468 return true;
469 }
470}
471
472auto SuffixTree::subwords(const Word& w, std::vector<std::pair<int,int>>& output) const -> bool
473{
474 return subwords(w,output,false);
475}
476
478 std::vector<std::pair<int,int>>& output,
479 bool onlyFirst) const -> bool
480{
481 // this command returns a pair (i,j) where word i in the table appears
482 // in position j of word.
483 auto cLocus = mRoot;
484 auto beta = Word();
485 Word tmpLabel = w;
486 int pos = 0;
487 bool retval = false;
488 std::cout << *(this->mRoot) << std::endl;
489 std::cout << w << std::endl;
490 while (tmpLabel.size() != 0)
491 {
492 SubwordsType swType;
493 if (cLocus == mRoot)
494 swType = subwordsStepD(mRoot,tmpLabel);
495 else
496 swType = subwordsStepC(cLocus->suffixLink(),beta,tmpLabel);
497 auto newcLocus = std::get<0>(swType);
498 auto newbeta = std::get<1>(swType);
499 auto leaf = std::get<2>(swType);
500 auto wasPattern = std::get<3>(swType);
501 //if (wasPattern && isPatternPrefix(leaf->label(),tmpLabel,newcLocus->label().size()+newbeta.size()))
502 if (wasPattern && isPatternPrefix(Word(leaf->label()),tmpLabel))
503 {
504 std::cout << Word(leaf->label()) << " " << tmpLabel << std::endl << std::flush;
505 auto tmp = std::make_pair(leaf->getPatternNumber(),pos);
506 output.push_back(tmp);
507 retval = true;
508 if (onlyFirst) return true;
509 }
510 pos++;
511 cLocus = newcLocus;
512 beta = newbeta;
513 tmpLabel = suffix(tmpLabel,1);
514 std::cout << *cLocus << " " << tmpLabel << std::endl;
515 }
516 return retval;
517}
518
520 const Word& beta,
521 const Word& s) const -> SubwordsType
522{
523 if (beta.size() == 0)
524 return subwordsStepD(x,suffix(s,x->label().size()));
525 auto elType = extendedLocus(x,beta);
526 auto f = std::get<0>(elType);
527 auto betaHat = std::get<1>(elType);
528 if (f->arcLabel().size() == betaHat.size())
529 return subwordsStepD(f,suffix(s,f->label().size()));
530 else
531 return std::make_tuple(f->parent(),betaHat,nullptr,false);
532}
533
535 const Word& s) const -> SubwordsType
536{
537 auto clType = contractedLocus(y,s);
538 auto newy = std::get<0>(clType);
539 auto f = std::get<1>(clType);
540 auto pre = std::get<2>(clType);
541 if (f == nullptr)
542 return std::make_tuple(newy,pre,nullptr,false);
543 else
544 return std::make_tuple(newy,pre,f,f->isFullPattern());
545}
546
547// the output is a list of pairs (i,j) such that the word w appears in monomial i in position j
548auto SuffixTree::superword(const Word& w, std::pair<int,int>& output) const -> bool
549{
550 auto tmp = std::vector<std::pair<int,int>> {};
551 superwords(w,tmp,true);
552 if (tmp.size() == 0) return false;
553 else
554 {
555 output = *(tmp.begin());
556 return true;
557 }
558}
559
560// the output is a list of pairs (i,j) such that the word w appears in monomial i in position j
561auto SuffixTree::superwords(const Word& w, std::vector<std::pair<int,int>>& output) const -> bool
562{
563 return superwords(w,output,false);
564}
565
566// the output is a list of pairs (i,j) such that the word w appears in monomial i in position j
567auto SuffixTree::superwords(const Word& w, std::vector<std::pair<int,int>>& output,bool onlyFirst) const -> bool
568{
569 auto clType = contractedLocus(mRoot,w);
570 auto y = std::get<0>(clType);
571 auto f = std::get<1>(clType);
572 auto pre = std::get<2>(clType);
573
574 if (!concatenatesTo(Word(y->label()),pre,w)) return false;
575 else if (f == nullptr)
576 {
577 auto leaves = std::vector<SuffixTreeNode*> {};
578 allLeaves(y,leaves);
579 for (auto g : leaves)
580 {
581 output.push_back(std::make_pair(g->getPatternNumber(),mMonomials[g->getPatternNumber()].size() - g->label().size() + 1));
582 if (onlyFirst) return true;
583 }
584 }
585 else if (f->isLeaf() && f->label().size() == w.size() + 1)
586 {
587 output.push_back(std::make_pair(f->getPatternNumber(),mMonomials[f->getPatternNumber()].size() - f->label().size() + 1));
588 return true;
589 }
590 return false;
591}
592
593// the output is a list of pairs (i,j) where monomial i overlaps properly with w in position j
594// in other words, the proper prefixes of w that are also suffixes in the tree
596 std::vector<std::pair<int,int>>& output,
597 bool avoidLast) const -> void
598{
599 auto tmpNode = mRoot;
600 auto tmpLabel = w;
601 auto match = findMatch(tmpNode,tmpLabel);
602 auto f = std::get<0>(match);
603 auto pre = std::get<1>(match);
604 int patternNum = -1;
605 while (f != nullptr && pre == Word(f->arcLabel()))
606 {
607 // in this case, the prefix found matches the arc label, so we move down
608 // the tree
609 tmpNode = f;
610 tmpLabel = suffix(tmpLabel,pre.size());
611 // after we move down add all children of tmpNode that are suffix leaves to leftOverlaps
612 // as long as tmpNode is not the root
613 for (auto i = tmpNode->childrenBegin(); i != tmpNode->childrenEnd(); ++i)
614 {
615 if (i->second->isLeaf() && !i->second->isFullPattern())
616 {
617 patternNum = i->second->getPatternNumber();
618 if (!(avoidLast && patternNum == mMonomials.size()-1))
619 output.push_back(std::make_pair(patternNum,
620 mMonomials[patternNum].size()-tmpNode->label().size()));
621 }
622 }
623 match = findMatch(tmpNode,tmpLabel);
624 f = std::get<0>(match);
625 pre = std::get<1>(match);
626 }
627 // At this point, if pre != {} then there is a common prefix to a child, but
628 // the label is not a full match to s. In this case, we add
629 // the unique suffix leaf that shares a prefix to our list,
630 // as long as it is not a full pattern
631 if (pre.size() != 0 && !f->isFullPattern())
632 {
633 patternNum = f->getPatternNumber();
634 if (!(avoidLast && patternNum == mMonomials.size()-1))
635 output.push_back(std::make_pair(patternNum,mMonomials[patternNum].size()-pre.size()));
636 }
637 return;
638}
639
641
642// size_t SuffixTree::insert(Word w)
643// {
644// Label tmp(w.begin(),w.end());
645// auto tmp2 = std::vector<Overlap> {};
646// return insert(tmp,tmp2);
647// }
648
649const Word SuffixTree::operator[](int index) const
650{
651 Word tmp(&*mMonomials[index].begin(),&*mMonomials[index].end());
652 return tmp;
653}
654
655// bool SuffixTree::subwords(const Word& word,
656// std::vector<std::pair<int,int>>& output) const
657// {
658// Label tmp(word.begin(),word.end());
659// return subwords(tmp,output);
660// }
661
662// bool SuffixTree::subword(const Word& word,
663// std::pair<int,int>& output) const
664// {
665// Label tmp(word.begin(),word.end());
666// return subword(tmp, output);
667// }
668
669// bool SuffixTree::superwords(const Word& word,
670// std::vector<std::pair<int,int>>& output) const
671// {
672// Label tmp(word.begin(),word.end());
673// return superwords(tmp,output);
674// }
675
676// this command returns true if word = alpha . v . beta for some v in the
677// word table, where if v = wordTable[index1], then alpha is not empty
678// and if v = wordTable[index2] then beta is not empty. Otherwise, it returns false.
679auto SuffixTree::isNontrivialSuperword(const Word& word, int index1, int index2) const -> bool
680{
681 //Label tmp(word.begin(),word.end());
682 std::vector<std::pair<int,int>> subs {};
683 subwords(word, subs);
684 for (auto sw : subs)
685 {
686 auto index = std::get<0>(sw);
687 auto pos = std::get<1>(sw);
688 if (index != index1 && index != index2) return true;
689 if (index != index1 && pos == 0) return true;
690 if (index != index2 && pos == word.size() - mMonomials[index2].size()) return true;
691 }
692 return false;
693}
694
695// this function computes the left overlaps of the most recently inserted monomial
696// with the rest of the tree, but not matching itself (by convention, that is considered a right overlap)
697auto SuffixTree::leftOverlaps(std::vector<Overlap>& output) const -> void
698{
699 if (mMonomials.size() == 0) return;
700 auto tmpLabel = *(mMonomials.end()-1);
701 auto pairs = std::vector<std::pair<int,int>> {};
702 leftOverlaps(Word(tmpLabel),pairs,true);
703 for (auto p : pairs)
704 {
705 output.push_back(std::make_tuple(p.first, p.second, mMonomials.size()-1,true));
706 }
707 return;
708}
709
710// Local Variables:
711// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
712// indent-tabs-mode: nil
713// End:
std::vector< int > word
Word prefix(const Word vec, int lengthOfPrefix)
bool isPatternPrefix(const Word a, const Word b, int startIndex)
std::ostream & operator<<(std::ostream &o, const SuffixTreeNode &suffixTreeNode)
void outputLabel(std::ostream &o, const Label &vec)
Definition SuffixTree.cpp:6
bool concatenatesTo(const Word a, const Word b, const Word c)
void outputPatterns(std::ostream &o, const SuffixTree &suffixTree)
Word suffix(const Word vec, int indexOfSuffix)
std::tuple< SuffixTreeNode *, SuffixTreeNode *, SuffixTreeNode * > InsertType
std::tuple< SuffixTreeNode *, SuffixTreeNode *, Word > ContractedLocusType
void outputLabel(std::ostream &o, const Label &vec)
Definition SuffixTree.cpp:6
std::tuple< SuffixTreeNode *, Word, SuffixTreeNode *, bool > SubwordsType
std::tuple< SuffixTreeNode *, Word > ExtendedLocusType
std::vector< int > Label
SuffixTree / SuffixTreeNode — experimental generalised suffix tree for non-commutative leading-word l...
Word and WordWithData — non-owning views over the flat-int encoding of a non-commutative word.
auto subwordsStepC(SuffixTreeNode *x, const Word &beta, const Word &s) const -> SubwordsType
auto contractedLocus(SuffixTreeNode *y, const Word &s, bool incrementLeafCount=false) const -> ContractedLocusType
auto insertStepD(SuffixTreeNode *y, const Word &s, bool isFullPattern) -> InsertType
auto extendedLocus(SuffixTreeNode *x, const Word &beta) const -> ExtendedLocusType
auto patternLeaves(SuffixTreeNode *v, std::vector< int > &output) const -> void
auto sharedPrefix(const Word s, const Word t) const -> Word
void leftOverlaps(std::vector< Overlap > &output) const
size_t insert(const Word &w)
auto isNontrivialSuperword(const Word &word, int index1, int index2) const -> bool
void destroyChildren(SuffixTreeNode *node) const
bool superwords(const Word &word, std::vector< std::pair< int, int > > &output) const
auto findMatch(SuffixTreeNode *y, const Word &s) const -> ExtendedLocusType
bool subwords(const Word &word, std::vector< std::pair< int, int > > &output) const
auto insertStepC(SuffixTreeNode *v, SuffixTreeNode *x, const Word &beta, const Word &s, bool isFullPattern) -> InsertType
SuffixTreeNode * mRoot
bool subword(const Word &word, std::pair< int, int > &output) const
const Word operator[](int index) const
Here begin the functions to make the new class swappable with the old WordTable.
auto patternLeavesWorker(SuffixTreeNode *v) const -> std::vector< SuffixTreeNode * >
std::vector< Label > mMonomials
auto allLeaves(SuffixTreeNode *v, std::vector< SuffixTreeNode * > &output) const -> void
auto splitArc(SuffixTreeNode *f, const Word &prefix) -> SuffixTreeNode *
auto superword(const Word &w, std::pair< int, int > &output) const -> bool
auto subwordsStepD(SuffixTreeNode *y, const Word &s) const -> SubwordsType
std::ostream & dump(std::ostream &, int depth, bool dumpChildren=true) const
SuffixTreeNode * mParent
SuffixTreeNode * mSuffixLink
std::map< Label, SuffixTreeNode * > mChildren
One node of a generalised suffix tree built over the inserted non-commutative monomial patterns.
const int * begin() const
Definition Word.hpp:72
const int * end() const
Definition Word.hpp:73
int size() const
Definition Word.hpp:74
Non-owning view of a non-commutative word: [begin, end) of int variable indices.
Definition Word.hpp:56
int p
void size_t s
Definition m2-mem.cpp:271
volatile int x
TermIterator< Nterm > begin(Nterm *ptr)
Definition ringelem.cpp:4
TermIterator< Nterm > end(Nterm *)
Definition ringelem.cpp:5