Встала задача для сопоставления предложений. Решалась следующим образом: использовался алгоритм для определения дистанции редактирования, разработанный Владимиром Левенштейном.
Реализация данного алгоритма на C#:
Реализация данного алгоритма на C#:
public class StringDistance
{
private int _absoluteMeasure;
/// Абсолютное значение функции похожести
public int AbsoluteMeasure
{
get { return _absoluteMeasure; }
}
private int _procentMeasure;
/// Относительное значение функции похожести
public int ProcentMeasure
{
get { return _procentMeasure; }
}
private string _sentenceOne;
private string _sentenceTwo;
public StringDistance(string sentenceOne, string sentenceTwo)
{
this._sentenceOne = sentenceOne;
this._sentenceTwo = sentenceTwo;
this.SentenceSeemsMeasure();
}
/// Вычисление меры схожести двух предложений
private void SentenceSeemsMeasure()
{
/// получение слов в предложениях
string[] sOneWords = _sentenceOne.Split(
new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
string[] sTwoWords = _sentenceTwo.Split(
new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
/// заполнение матрицы отношений между словами предложения
int[,] wordRelations = new int[sOneWords.Length, sTwoWords.Length];
// значения максимальных значений в строках матрицы
int[] maxRowElements = new int[sOneWords.Length];
try
{
for (int i = 0; i < sOneWords.Length; i++)
{
int max = 0;
for (int j = 0; j < sTwoWords.Length; j++)
{
// получение дистанции для пары слов в предлажении
wordRelations[i, j] =
StringDistance.GetWordDistance(
sOneWords[i], sTwoWords[j]);
// сравение с максимальным значением
if (max < wordRelations[i, j])
max = wordRelations[i, j];
}
maxRowElements[i] = max;
}
/// получения меры схожести между предложениями
int measure = 0;
for (int i = 0; i < maxRowElements.Length; i++)
{
int max = maxRowElements[i];
for (int j = 0; j < sTwoWords.Length; j++)
if (max < wordRelations[i, j])
max = wordRelations[i, j];
measure += max;
}
this._absoluteMeasure = measure;
// получения относительного значения схожести двух предложений
this._procentMeasure =
(int)Math.Round(
measure / (double)Math.Max(sOneWords.Length, sTwoWords.Length), 0);
}
catch (Exception ex)
{
throw new Exception("Ошибка при сравнении предложений", ex);
}
}
/// Получение дистанции для двух слов
private static int GetWordDistance(String s, String t)
{
try
{
/// шаг 1
if (string.IsNullOrEmpty(s) || string.IsNullOrEmpty(t))
throw new Exception("Одно из слов не задано.");
s = s.ToLower();
t = t.ToLower();
int n = s.Length; // длина строки s
int m = t.Length; // длина строки t
int[,] d =
new int[n + 1, m + 1]; // матрица для хранения вычислений
/// шаг 2
for (int i = 0; i <= n; i++)
d[i, 0] = i;
for (int j = 0; j <= m; j++)
d[0, j] = j;
/// шаг 3
for (int i = 1; i <= n; i++)
{
int s_i = s[i - 1];
for (int j = 1; j <= m; j++)
{
int t_j = t[j - 1];
int cost = 0;
// определение оценки
if (s_i != t_j)
cost = 1;
// получить минимум для ячейки матрцы
d[i, j] = Minimum(
d[i - 1, j] + 1,
d[i, j - 1] + 1,
d[i - 1, j - 1] + cost);
}
}
int dist = d[n, m]; // дистанция редактирования
/// получение относительного числа похожести
int procent = (int)Math.Round(
(1 - dist / (double)System.Math.Max(s.Length, t.Length)) * 100, 0);
return procent;
}
catch (Exception ex)
{
throw new Exception("Ошибка при сравнении слов", ex);
}
}
/// Минимум из трех значений
private static int Minimum(int a, int b, int c)
{
int min = a;
if (b < min)
min = b;
if (c < min)
min = c;
return min;
}
}
Комментариев нет:
Отправить комментарий