12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 |
- // Copyright (c) 2015, Arbo von Monkiewitsch All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license.
- package levenshtein
- // Context is the object which allows to calculate the Levenshtein distance
- // with Distance() method. It is needed to ensure 0 memory allocations.
- type Context struct {
- intSlice []int
- }
- func (c *Context) getIntSlice(l int) []int {
- if cap(c.intSlice) < l {
- c.intSlice = make([]int, l)
- }
- return c.intSlice[:l]
- }
- // Distance calculates the Levenshtein distance between two strings which
- // is defined as the minimum number of edits needed to transform one string
- // into the other, with the allowable edit operations being insertion, deletion,
- // or substitution of a single character
- // http://en.wikipedia.org/wiki/Levenshtein_distance
- //
- // This implementation is optimized to use O(min(m,n)) space.
- // It is based on the optimized C version found here:
- // http://en.wikibooks.org/wiki/Algorithm_implementation/Strings/Levenshtein_distance#C
- func (c *Context) Distance(str1, str2 string) int {
- s1 := []rune(str1)
- s2 := []rune(str2)
- lenS1 := len(s1)
- lenS2 := len(s2)
- if lenS2 == 0 {
- return lenS1
- }
- column := c.getIntSlice(lenS1 + 1)
- // Column[0] will be initialised at the start of the first loop before it
- // is read, unless lenS2 is zero, which we deal with above
- for i := 1; i <= lenS1; i++ {
- column[i] = i
- }
- for x := 0; x < lenS2; x++ {
- s2Rune := s2[x]
- column[0] = x + 1
- lastdiag := x
- for y := 0; y < lenS1; y++ {
- olddiag := column[y+1]
- cost := 0
- if s1[y] != s2Rune {
- cost = 1
- }
- column[y+1] = min(
- column[y+1]+1,
- column[y]+1,
- lastdiag+cost,
- )
- lastdiag = olddiag
- }
- }
- return column[lenS1]
- }
- func min(a, b, c int) int {
- if a < b {
- if a < c {
- return a
- }
- } else {
- if b < c {
- return b
- }
- }
- return c
- }
|