Ordnen Sie zwei Zeichenfolgen zu, berücksichtigen Sie jedoch einen gewissen Fehlergrad

10

Wie kann ich zwei Zeichenfolgen abgleichen, aber gleichzeitig zulassen, dass die X-Anzahl der Zeichen in der Übereinstimmung falsch ist? Die Anzahl der Fehler sollte eine steuerbare Variable sein.

Während die Anzahl der X-Zeichen in der Zeichenfolge nicht übereinstimmen kann, sollte die Anzahl der Zeichen in einer Sequenz begrenzt sein. Bei zwei Zeichenfolgen kann ich zulassen, dass 5 Zeichen unterschiedlich sind, jedoch nicht mehr als 2 in einer Reihe.

Ich suche nach einem empfohlenen Algorithmus zum Vergleichen dieser beiden Zeichenfolgen, oder vielleicht gibt es bereits eine bekannte Lösung dafür.

Reactgular
quelle
4
Die Levenshtein-Entfernung könnte etwas zu beachten sein, obwohl die Besonderheiten von "nicht mehr als 2 in einer Reihe" nicht Teil dieses Algorithmus sind. Auf der Seite "Siehe auch" finden Sie viele andere verwandte Algorithmen, nach denen Sie möglicherweise suchen.
@ MichaelT Wenn ich so etwas hätte, würde es definitiv meinen Bedürfnissen entsprechen. Vielen Dank.
Reactgular
@MichaelT Ich fand dies> dotnetperls.com/levenshtein Sie sollten das als Antwort angeben , da dies meine Probleme löste.
Reactgular
Vielleicht möchten Sie sich Soundex Matching ansehen. en.wikipedia.org/wiki/Soundex
Gilbert Le Blanc

Antworten:

12

Ein ungefährer Startpunkt für die Zeichenfolgensuche ist der der Levenshtein-Entfernung . Dieser Algorithmus zählt die Anzahl der Einzelzeichenänderungen (Einfügen, Löschen und Ersetzen), um ein Wort in ein anderes zu ändern.

Ein Beispiel hierfür ist kitten-> sittingmit einem Bearbeitungsabstand von drei

  1. k itten -> s itten (ersetzen Sie 'k' durch 's')
  2. sitt e n -> sitt i n ( ersetze 'e' durch 'i')
  3. sittin -> sittin g (füge 'g' am Ende hinzu)

Es gibt Variationen dieses Algorithmus, insbesondere den Damerau-Levenshtein-Abstand, der die Transposition zweier benachbarter Zeichen ermöglicht ('hte' zu 'the' hat einen DL-Abstand von 1 und einen Levenshtein-Abstand von 2) und ist daher häufig besser geeignet für Rechtschreibprüfung. Andere Variationen existieren für Anwendungen, bei denen Lücken wichtig sind (DNA-Strings).

Die Levenshtein-Entfernung ist bekannt und nicht allzu schwer zu finden (ich hatte einmal Grund, eine Implementierung als Funktion in Oracle zu suchen - sie war viel schneller, als alle Daten abzurufen und dann die Abfragecodeseite auszuführen). Rosettacode hat eine Vielzahl (54) von Implementierungen der Levenshtein-Distanz (beachten Sie, dass einige Sprachen dies irgendwo als Teil der String-Bibliothek haben - wenn Sie Java verwenden, schauen Sie sich die Apache Commons Lang an ). Wikibooks hat 31 Implementierungen und ein flüchtiger Blick auf die beiden zeigt nicht den gleichen Code für die gleiche Sprache.

Dies funktioniert so, dass eine Matrix aufgebaut wird, die der Beziehung zwischen den beiden Zeichenfolgen entspricht:

 .kitten
.0123456
s1123456
i2212345
t3321234
t4432123
i5543223
n6654332
g7765443

Die .Zeile und Spalte stellen dar, dass Sie zur Zielzeichenfolge gelangen können, indem Sie jeden Buchstaben aus einer leeren Zeichenfolge einfügen. Dies ist nicht der ideale Fall, aber er dient dazu, den Algorithmus zu bestimmen.

Wenn der Wert mit dem Punkt ('i' == 'i') identisch ist, entspricht der Wert dem Wert diagonal nach links. Wenn die beiden Punkte unterschiedlich sind ('s'! = 'K'), ist der Wert das Minimum von:

  • Diagonale nach oben und links + 1 (eine Substitution)
  • direkt über + 1 (eine Einfügung)
  • direkt links + 1 (eine Löschung)

Der Rückgabewert für die Bearbeitungsentfernung ist der Wert unten rechts in der Matrix.

Wenn Sie mit dem Minimum von rechts unten nach links oben folgen, können Sie die vorgenommenen Änderungen sehen:

 .kitten
.0.   .
s.1   .
i  1  .
t   1 .
t    1.
i.....2
n      2
g......3

Beachten Sie, dass dies der eher speicherintensive Ansatz ist. Der Speicherbereich kann reduziert werden, indem nicht die vollständige Matrix erstellt wird. Der Algorithmus kümmert sich lediglich um eine Teilmenge der Daten. Sie kann von N*MSpeicherplatz zu 2*max(N,M)Speicherplatz reduziert werden, indem nur die vorherige Zeile gespeichert wird (und was anhand des Stroms berechnet wurde) Reihe). Code Project zeigt, wie dies gemacht werden kann (mit C # -Code zum Herunterladen).

Gemeinschaft
quelle