it-swarm.com.de

Was sind einige Algorithmen zum Vergleichen, wie ähnlich zwei Zeichenfolgen sind?

Ich muss Zeichenfolgen vergleichen, um zu entscheiden, ob sie dasselbe darstellen. Dies bezieht sich auf von Menschen eingegebene Falltitel, bei denen Abkürzungen und andere kleine Details abweichen können. Betrachten Sie beispielsweise die folgenden beiden Titel:

std::string first = "Henry C. Harper v. The Law Offices of Huey & Luey, LLP";

Im Gegensatz zu:

std::string second = "Harper v. The Law Offices of Huey & Luey, LLP";

Ein Mensch kann schnell einschätzen, dass dies höchstwahrscheinlich ein und dasselbe ist. Der aktuelle Ansatz, den ich gewählt habe, besteht darin, die Zeichenfolgen zu normalisieren, indem alle Buchstaben mit einem Kürzel versehen und alle Satzzeichen und Leerzeichen entfernt werden.

std::string firstNormalized = "henrycharpervthelawofficesofhueylueyllp";

Und:

std::string secondNormalized = "harpervthelawofficesofhueylueyllp";

Wenn man in diesem Fall vergleicht, ist eine Sequenz eine Teilsequenz der anderen, aber Sie können sich andere komplexere Variationen vorstellen, bei denen dies nicht unbedingt der Fall ist, die jedoch signifikante Teilsequenzen gemeinsam haben. Es kann auch gelegentlich zu Eingabefehlern kommen, wie z. B. vertauschte Buchstaben und Rechtschreibfehler.

Vielleicht könnte eine Art Character Diff-Programm helfen? Ich habe gute Zeilendifferenz-Programme zum Vergleichen von Unterschieden im Code gesehen, die eingecheckt werden sollen. Gibt es so etwas auf Zeichenbasis, vielleicht im Boost-Modus? Wenn Sie die Anzahl der aufeinanderfolgenden Zeichen gemeinsam zählen und das Verhältnis zu den nicht freigegebenen Zeichen nehmen könnten, wäre das vielleicht eine gute Heuristik?

Am Ende brauche ich eine boolesche Entscheidung, ob ich sie gleich betrachten soll oder nicht. Es muss nicht perfekt sein, aber es sollte im Idealfall selten falsch sein.

Welchen Algorithmus kann ich verwenden, um zu quantifizieren, wie ähnlich die beiden Zeichenfolgen zueinander sind, und den ich dann mithilfe einer Heuristik in eine Ja/Nein-Antwort umwandeln kann?

51
WilliamKF

Was Sie suchen, heißen String Metric Algorithmen. Es gibt eine signifikante Anzahl von ihnen, viele mit ähnlichen Eigenschaften. Unter den beliebtesten:

  • Levenshtein Distance : Die minimale Anzahl von Einzelzeichenänderungen, die erforderlich sind, um ein Wort in das andere zu ändern. Zeichenfolgen müssen nicht gleich lang sein
  • Hamming Distance : Die Anzahl der Zeichen, die sich in zwei gleich langen Zeichenfolgen unterscheiden.
  • Smith-Waterman : Eine Familie von Algorithmen zur Berechnung von Ähnlichkeiten variabler Teilsequenzen.
  • Sørensen-Dice-Koeffizient : Ein Ähnlichkeitsalgorithmus, der Differenzkoeffizienten benachbarter Zeichenpaare berechnet.

Schauen Sie sich diese und andere auf der Wiki-Seite zum Thema an.

75
Daniel Frey

Damerau Levenshtein distance ist ein weiterer Algorithmus zum Vergleichen von zwei Zeichenfolgen und ähnelt dem Levenshtein distance-Algorithmus. Der Unterschied zwischen den beiden besteht darin, dass sie auch die Transpositionen zwischen Zeichen überprüfen und somit ein besseres Ergebnis für die Fehlerkorrektur liefern können.

Beispiel: Der Levenshtein-Abstand zwischen night und nigth beträgt 2, während der Damerau Levenshtein-Abstand zwischen night und nigth 1 beträgt, da es sich nur um einen Swap von handelt ein Zeichenpaar.

10
Ankit Chaurasia

Sie könnten dafür ngrams verwenden. Transformieren Sie beispielsweise die beiden Zeichenfolgen in Word-Trigrammen (normalerweise in Kleinbuchstaben) und vergleichen Sie den Prozentsatz der Zeichenfolgen, die einander entsprechen.

Ihre Herausforderung besteht darin, einen Mindestprozentsatz für die Ähnlichkeit zu definieren.

http://en.wikipedia.org/wiki/N-gram

3
noderman

Ein weiterer Algorithmus, den Sie berücksichtigen können, ist die Simon White-Ähnlichkeit:

def get_bigrams(string):
    """
    Take a string and return a list of bigrams.
    """
    if string is None:
        return ""

    s = string.lower()
    return [s[i : i + 2] for i in list(range(len(s) - 1))]
def simon_similarity(str1, str2):
    """
    Perform bigram comparison between two strings
    and return a percentage match in decimal form.
    """
    pairs1 = get_bigrams(str1)
    pairs2 = get_bigrams(str2)
    union = len(pairs1) + len(pairs2)

    if union == 0 or union is None:
        return 0

    hit_count = 0
    for x in pairs1:
        for y in pairs2:
            if x == y:
                hit_count += 1
                break
    return (2.0 * hit_count) / union
2

Sie können den Algorithmus zum Berechnen der Länge der längsten gemeinsamen Teilsequenz verwenden, um das Problem zu lösen. Wenn die Länge der längsten gemeinsamen Teilsequenz für beide Eingabezeichenfolgen geringer ist als die Länge einer der Zeichenfolgen, sind sie ungleich.

Sie können den Ansatz der dynamischen Programmierung verwenden, um das Problem zu lösen und die Raumkomplexität zu optimieren, falls Sie nicht die längste gemeinsame Teilsequenz herausfinden möchten.

0
nmg_vikas