Редактировать расстояние в Python - PullRequest
28 голосов
/ 17 марта 2010

Я программирую программу проверки орфографии в Python. У меня есть список допустимых слов (словарь), и мне нужно вывести список слов из этого словаря, которые имеют расстояние редактирования 2 от данного недопустимого слова.

Я знаю, что мне нужно начать с создания списка с расстоянием редактирования, равным единице, от недопустимого слова (а затем снова запустить его для всех сгенерированных слов). У меня есть три метода: вставки (...), удаления (...) и изменения (...), которые должны выводить список слов с расстоянием редактирования 1, где вставки выводит все допустимые слова с еще одной буквой, чем данное слово, delete выводит все допустимые слова на одну букву меньше, а изменения выводит все допустимые слова на одну другую букву.

Я проверил кучу мест, но я не могу найти алгоритм, который описывает этот процесс. Все идеи, которые я выдвинул, включают в себя многократный цикл по списку словарей, что потребовало бы очень много времени. Если бы кто-нибудь мог предложить какое-то понимание, я был бы чрезвычайно благодарен.

Ответы [ 7 ]

46 голосов
/ 14 сентября 2015

То, на что вы смотрите, называется расстоянием редактирования, а вот хорошее объяснение в вики . Существует множество способов определить расстояние между двумя словами и тем, которое вы хотите, называется расстоянием Левенштейна, и вот реализация DP в python.

def levenshteinDistance(s1, s2):
    if len(s1) > len(s2):
        s1, s2 = s2, s1

    distances = range(len(s1) + 1)
    for i2, c2 in enumerate(s2):
        distances_ = [i2+1]
        for i1, c1 in enumerate(s1):
            if c1 == c2:
                distances_.append(distances[i1])
            else:
                distances_.append(1 + min((distances[i1], distances[i1 + 1], distances_[-1])))
        distances = distances_
    return distances[-1]

И пара дополнительных реализаций здесь .

10 голосов
/ 12 июня 2014

Вот моя версия для расстояния Левенштейна

def edit_distance(s1, s2):
    m=len(s1)+1
    n=len(s2)+1

    tbl = {}
    for i in range(m): tbl[i,0]=i
    for j in range(n): tbl[0,j]=j
    for i in range(1, m):
        for j in range(1, n):
            cost = 0 if s1[i-1] == s2[j-1] else 1
            tbl[i,j] = min(tbl[i, j-1]+1, tbl[i-1, j]+1, tbl[i-1, j-1]+cost)

    return tbl[i,j]

print(edit_distance("Helloworld", "HalloWorld"))
8 голосов
/ 12 ноября 2013
#this calculates edit distance not levenstein edit distance
word1="rice"

word2="ice"

len_1=len(word1)

len_2=len(word2)

x =[[0]*(len_2+1) for _ in range(len_1+1)]#the matrix whose last element ->edit distance

for i in range(0,len_1+1): #initialization of base case values

    x[i][0]=i
for j in range(0,len_2+1):

    x[0][j]=j
for i in range (1,len_1+1):

    for j in range(1,len_2+1):

        if word1[i-1]==word2[j-1]:
            x[i][j] = x[i-1][j-1] 

        else :
            x[i][j]= min(x[i][j-1],x[i-1][j],x[i-1][j-1])+1

print x[i][j]
2 голосов
/ 17 марта 2010

Конкретный алгоритм, который вы описываете, называется расстоянием Левенштейна. Быстрый Google подбрасывает несколько библиотек Python и рецептов для его расчета.

1 голос
/ 29 апреля 2019

difflib в стандартной библиотеке есть различные утилиты для сопоставления последовательностей, включая метод get_close_matches, который вы можете использовать. Он использует алгоритм, адаптированный из Ratcliff и Obershelp.

Из документов

from difflib import get_close_matches

# Yields ['apple', 'ape']
get_close_matches('appel', ['ape', 'apple', 'peach', 'puppy'])
1 голос
/ 03 декабря 2018

Для этой задачи вам нужно минимальное расстояние редактирования.

Ниже приводится моя версия MED a.k.a Levenshtein Distance.

def MED_character(str1,str2):
    cost=0
    len1=len(str1)
    len2=len(str2)

    #output the length of other string in case the length of any of the string is zero
    if len1==0:
        return len2
    if len2==0:
        return len1

    accumulator = [[0 for x in range(len2)] for y in range(len1)] #initializing a zero matrix

    # initializing the base cases
    for i in range(0,len1):
        accumulator[i][0] = i;
    for i in range(0,len2):
        accumulator[0][i] = i;

    # we take the accumulator and iterate through it row by row. 
    for i in range(1,len1):
        char1=str1[i]
        for j in range(1,len2):
            char2=str2[j]
            cost1=0
            if char1!=char2:
                cost1=2 #cost for substitution
            accumulator[i][j]=min(accumulator[i-1][j]+1, accumulator[i][j-1]+1, accumulator[i-1][j-1] + cost1 )

    cost=accumulator[len1-1][len2-1]
    return cost
0 голосов
/ 01 апреля 2017

Вместо алгоритма расстояния Левенштейна используйте BK tree или TRIE , поскольку эти алгоритмы имеют меньшую сложность, чем редактирование расстояния. Хороший обзор по этой теме даст подробное описание.

Эта ссылка поможет вам больше о проверке орфографии.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...