123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- package diffmatchpatch
- import (
- "math"
- )
- func (dmp *DiffMatchPatch) MatchMain(text, pattern string, loc int) int {
-
- loc = int(math.Max(0, math.Min(float64(loc), float64(len(text)))))
- if text == pattern {
-
- return 0
- } else if len(text) == 0 {
-
- return -1
- } else if loc+len(pattern) <= len(text) && text[loc:loc+len(pattern)] == pattern {
-
- return loc
- }
-
- return dmp.MatchBitap(text, pattern, loc)
- }
- func (dmp *DiffMatchPatch) MatchBitap(text, pattern string, loc int) int {
-
- s := dmp.MatchAlphabet(pattern)
-
- scoreThreshold := dmp.MatchThreshold
-
- bestLoc := indexOf(text, pattern, loc)
- if bestLoc != -1 {
- scoreThreshold = math.Min(dmp.matchBitapScore(0, bestLoc, loc,
- pattern), scoreThreshold)
-
- bestLoc = lastIndexOf(text, pattern, loc+len(pattern))
- if bestLoc != -1 {
- scoreThreshold = math.Min(dmp.matchBitapScore(0, bestLoc, loc,
- pattern), scoreThreshold)
- }
- }
-
- matchmask := 1 << uint((len(pattern) - 1))
- bestLoc = -1
- var binMin, binMid int
- binMax := len(pattern) + len(text)
- lastRd := []int{}
- for d := 0; d < len(pattern); d++ {
-
- binMin = 0
- binMid = binMax
- for binMin < binMid {
- if dmp.matchBitapScore(d, loc+binMid, loc, pattern) <= scoreThreshold {
- binMin = binMid
- } else {
- binMax = binMid
- }
- binMid = (binMax-binMin)/2 + binMin
- }
-
- binMax = binMid
- start := int(math.Max(1, float64(loc-binMid+1)))
- finish := int(math.Min(float64(loc+binMid), float64(len(text))) + float64(len(pattern)))
- rd := make([]int, finish+2)
- rd[finish+1] = (1 << uint(d)) - 1
- for j := finish; j >= start; j-- {
- var charMatch int
- if len(text) <= j-1 {
-
- charMatch = 0
- } else if _, ok := s[text[j-1]]; !ok {
- charMatch = 0
- } else {
- charMatch = s[text[j-1]]
- }
- if d == 0 {
-
- rd[j] = ((rd[j+1] << 1) | 1) & charMatch
- } else {
-
- rd[j] = ((rd[j+1]<<1)|1)&charMatch | (((lastRd[j+1] | lastRd[j]) << 1) | 1) | lastRd[j+1]
- }
- if (rd[j] & matchmask) != 0 {
- score := dmp.matchBitapScore(d, j-1, loc, pattern)
-
- if score <= scoreThreshold {
-
- scoreThreshold = score
- bestLoc = j - 1
- if bestLoc > loc {
-
- start = int(math.Max(1, float64(2*loc-bestLoc)))
- } else {
-
- break
- }
- }
- }
- }
- if dmp.matchBitapScore(d+1, loc, loc, pattern) > scoreThreshold {
-
- break
- }
- lastRd = rd
- }
- return bestLoc
- }
- func (dmp *DiffMatchPatch) matchBitapScore(e, x, loc int, pattern string) float64 {
- accuracy := float64(e) / float64(len(pattern))
- proximity := math.Abs(float64(loc - x))
- if dmp.MatchDistance == 0 {
-
- if proximity == 0 {
- return accuracy
- }
- return 1.0
- }
- return accuracy + (proximity / float64(dmp.MatchDistance))
- }
- func (dmp *DiffMatchPatch) MatchAlphabet(pattern string) map[byte]int {
- s := map[byte]int{}
- charPattern := []byte(pattern)
- for _, c := range charPattern {
- _, ok := s[c]
- if !ok {
- s[c] = 0
- }
- }
- i := 0
- for _, c := range charPattern {
- value := s[c] | int(uint(1)<<uint((len(pattern)-i-1)))
- s[c] = value
- i++
- }
- return s
- }
|