Пример #1
0
        public int LevenshteinDistance <T>(T[] strOld,
                                           T[] strNew,
                                           IEqualityComparer <T> comparer = null,
                                           Func <Choice <T>, int> weight  = null,
                                           bool allowTransposition        = false)
        {
            var m1 = strOld.Length + 1;
            var m2 = strNew.Length + 1;

            if (comparer == null)
            {
                comparer = EqualityComparer <T> .Default;
            }

            if (weight == null)
            {
                weight = c => 1;
            }

            _ResizeArray(m1, m2);

            _num[0, 0] = 0;

            for (var i = 1; i < m1; i++)
            {
                _num[i, 0] = _num[i - 1, 0] + weight(Choice <T> .Remove(strOld[i - 1]));
            }
            for (var j = 1; j < m2; j++)
            {
                _num[0, j] = _num[0, j - 1] + weight(Choice <T> .Add(strNew[j - 1]));
            }

            for (var i = 1; i < m1; i++)
            {
                for (var j = 1; j < m2; j++)
                {
                    if (comparer.Equals(strOld[i - 1], strNew[j - 1]))
                    {
                        _num[i, j] = _num[i - 1, j - 1];
                    }
                    else
                    {
                        _num[i, j] = Math.Min(Math
                                              .Min(
                                                  _num[i - 1, j] + weight(Choice <T> .Remove(strOld[i - 1])),
                                                  _num[i, j - 1] + weight(Choice <T> .Add(strNew[j - 1]))
                                                  ),
                                              _num[i - 1, j - 1] + weight(Choice <T> .Substitute(strOld[i - 1], strNew[j - 1]))
                                              );

                        if (allowTransposition && i > 1 &&
                            j > 1 &&
                            comparer.Equals(strOld[i - 1], strNew[j - 2]) &&
                            comparer.Equals(strOld[i - 2], strNew[j - 1]))
                        {
                            _num[i, j] = Math.Min(_num[i, j],
                                                  _num[i - 2, j - 2] + weight(Choice <T> .Transpose(strOld[i - 1], strOld[i - 2])));
                        }
                    }
                }
            }

            return(_num[m1 - 1, m2 - 1]);
        }
Пример #2
0
        public List <Choice <T> > LevenshteinChoices <T>(T[] strOld,
                                                         T[] strNew,
                                                         IEqualityComparer <T> comparer = null,
                                                         Func <Choice <T>, int> weight  = null)
        {
            if (comparer == null)
            {
                comparer = EqualityComparer <T> .Default;
            }

            if (weight == null)
            {
                weight = c => 1;
            }

            LevenshteinDistance(strOld, strNew, comparer, weight);

            var i = strOld.Length;
            var j = strNew.Length;

            var result = new List <Choice <T> >();

            while (i > 0 && j > 0)
            {
                if (comparer.Equals(strOld[i - 1], strNew[j - 1]))
                {
                    result.Add(Choice <T> .Equal(strOld[i - 1]));

                    i = i - 1;
                    j = j - 1;
                }
                else
                {
                    var cRemove = Choice <T> .Remove(strOld[i - 1]);

                    var cAdd = Choice <T> .Add(strNew[j - 1]);

                    var cSubstitute = Choice <T> .Substitute(strOld[i - 1], strNew[j - 1]);

                    var remove     = _num[i - 1, j] + weight(cRemove);
                    var add        = _num[i, j - 1] + weight(cAdd);
                    var substitute = _num[i - 1, j - 1] + weight(cSubstitute);

                    var min = Math.Min(remove, Math.Min(add, substitute));

                    if (substitute == min)
                    {
                        result.Add(cSubstitute);

                        i = i - 1;
                        j = j - 1;
                    }
                    else if (remove == min)
                    {
                        result.Add(cRemove);

                        i = i - 1;
                    }
                    else if (add == min)
                    {
                        result.Add(cAdd);

                        j = j - 1;
                    }
                }
            }

            while (i > 0)
            {
                result.Add(Choice <T> .Remove(strOld[i - 1]));

                i = i - 1;
            }

            while (j > 0)
            {
                result.Add(Choice <T> .Add(strNew[j - 1]));

                j = j - 1;
            }

            result.Reverse();

            return(result);
        }