gopkg.in/alecthomas/gometalinter.v3@v3.0.0/_linters/src/github.com/mibk/dupl/suffixtree/dupl.go (about)

     1  package suffixtree
     2  
     3  import "sort"
     4  
     5  type Match struct {
     6  	Ps  []Pos
     7  	Len Pos
     8  }
     9  
    10  type posList struct {
    11  	positions []Pos
    12  }
    13  
    14  func newPosList() *posList {
    15  	return &posList{make([]Pos, 0)}
    16  }
    17  
    18  func (p *posList) append(p2 *posList) {
    19  	p.positions = append(p.positions, p2.positions...)
    20  }
    21  
    22  func (p *posList) add(pos Pos) {
    23  	p.positions = append(p.positions, pos)
    24  }
    25  
    26  type contextList struct {
    27  	lists map[int]*posList
    28  }
    29  
    30  func newContextList() *contextList {
    31  	return &contextList{make(map[int]*posList)}
    32  }
    33  
    34  func (c *contextList) getAll() []Pos {
    35  	keys := make([]int, 0, len(c.lists))
    36  	for k := range c.lists {
    37  		keys = append(keys, k)
    38  	}
    39  	sort.Ints(keys)
    40  	var ps []Pos
    41  	for _, k := range keys {
    42  		ps = append(ps, c.lists[k].positions...)
    43  	}
    44  	return ps
    45  }
    46  
    47  func (c *contextList) append(c2 *contextList) {
    48  	for lc, pl := range c2.lists {
    49  		if _, ok := c.lists[lc]; ok {
    50  			c.lists[lc].append(pl)
    51  		} else {
    52  			c.lists[lc] = pl
    53  		}
    54  	}
    55  }
    56  
    57  // FindDuplOver find pairs of maximal duplicities over a threshold
    58  // length.
    59  func (t *STree) FindDuplOver(threshold int) <-chan Match {
    60  	auxTran := newTran(0, 0, t.root)
    61  	ch := make(chan Match)
    62  	go func() {
    63  		walkTrans(auxTran, 0, threshold, ch)
    64  		close(ch)
    65  	}()
    66  	return ch
    67  }
    68  
    69  func walkTrans(parent *tran, length, threshold int, ch chan<- Match) *contextList {
    70  	s := parent.state
    71  
    72  	cl := newContextList()
    73  
    74  	if len(s.trans) == 0 {
    75  		pl := newPosList()
    76  		start := parent.end + 1 - Pos(length)
    77  		pl.add(start)
    78  		ch := 0
    79  		if start > 0 {
    80  			ch = s.tree.data[start-1].Val()
    81  		}
    82  		cl.lists[ch] = pl
    83  		return cl
    84  	}
    85  
    86  	for _, t := range s.trans {
    87  		ln := length + t.len()
    88  		cl2 := walkTrans(t, ln, threshold, ch)
    89  		if ln >= threshold {
    90  			cl.append(cl2)
    91  		}
    92  	}
    93  	if length >= threshold && len(cl.lists) > 1 {
    94  		m := Match{cl.getAll(), Pos(length)}
    95  		ch <- m
    96  	}
    97  	return cl
    98  }