Der Bearbeitungsabstand (oder Levenshtein-Abstand) zwischen zwei Zeichenfolgen ist die minimale Anzahl von Einfügungen, Löschungen und Ersetzungen einzelner Zeichen, die erforderlich sind, um eine Zeichenfolge in die andere umzuwandeln. Wenn die beiden Zeichenfolgen jeweils die Länge n haben, ist bekannt, dass dies durch dynamische Programmierung in O (n ^ 2) -Zeit erfolgen kann. Der folgende Python-Code führt diese Berechnung für zwei Zeichenfolgen s1
und durch s2
.
def edit_distance(s1, s2):
l1 = len(s1)
l2 = len(s2)
matrix = [range(l1 + 1)] * (l2 + 1)
for zz in range(l2 + 1):
matrix[zz] = range(zz,zz + l1 + 1)
for zz in range(0,l2):
for sz in range(0,l1):
if s1[sz] == s2[zz]:
matrix[zz+1][sz+1] = min(matrix[zz+1][sz] + 1, matrix[zz][sz+1] + 1, matrix[zz][sz])
else:
matrix[zz+1][sz+1] = min(matrix[zz+1][sz] + 1, matrix[zz][sz+1] + 1, matrix[zz][sz] + 1)
return matrix[l2][l1]
Bei dieser Aufgabe müssen Sie so nah wie möglich an der Berechnung der Bearbeitungsentfernung sein, jedoch mit einer starken Speicherbeschränkung. Ihr Code darf ein Array mit 1000 32-Bit-Ganzzahlen definieren. Dies ist der einzige temporäre Speicher, den Sie für Ihre Berechnung verwenden. Alle Variablen und Datenstrukturen sollen in diesem Array enthalten sein. Insbesondere könnten Sie den obigen Algorithmus für Zeichenfolgen mit einer Länge von 1000 nicht implementieren, da Sie mindestens 1.000.000 Zahlen speichern müssten. Wenn Ihre Sprache natürlich keine 32-Bit-Ganzzahlen enthält (z. B. Python), müssen Sie lediglich sicherstellen, dass Sie niemals eine Zahl größer als 2 ^ 32-1 im Array speichern.
Sie können die Daten mit einer beliebigen Standardbibliothek Ihrer Wahl einlesen, ohne sich über die Speicherbeschränkungen in diesem Teil Gedanken machen zu müssen. Um den Wettbewerb für den Hauptteil Ihres Codes fair zu gestalten, dürfen Sie nur Operationen verwenden, die funktional denen in der Programmiersprache C entsprechen und keine externen Bibliotheken verwenden können.
Um besonders klar zu sein, zählt der Speicher zum Speichern der Eingabedaten oder der vom Interpreter Ihrer Sprache, JVM usw. verwendete Speicher nicht zu Ihrem Limit und Sie können möglicherweise nichts auf die Festplatte schreiben. Sie müssen davon ausgehen, dass die Eingabedaten im Speicher schreibgeschützt sind, damit Sie sie nicht wiederverwenden können, um mehr Arbeitsraum zu gewinnen.
Was muss ich implementieren?
Ihr Code sollte eine Datei im folgenden Format einlesen. Es wird drei Zeilen haben. Die erste Zeile ist der wahre Bearbeitungsabstand. Die zweite ist Zeichenfolge 1 und die dritte ist Zeichenfolge 2. Ich werde sie mit den Beispieldaten unter https://bpaste.net/show/6905001d52e8 testen, wobei die Zeichenfolgen eine Länge von 10.000 haben, sie sollten jedoch nicht auf diese Daten spezialisiert sein. Es sollte den kleinsten Bearbeitungsabstand ausgeben, den es zwischen den beiden Zeichenfolgen finden kann.
Sie müssen auch nachweisen, dass Ihre Bearbeitungsentfernung tatsächlich aus einem gültigen Satz von Änderungen stammt. Ihr Code sollte einen Schalter haben, der ihn in einen Modus verwandelt, der möglicherweise mehr Speicher benötigt (so viel Sie möchten) und die Bearbeitungsvorgänge ausgibt, die Ihre Bearbeitungsentfernung angeben.
Ergebnis
Ihre Punktzahl wird die sein (optimal edit distance/divided by the edit distance you find) * 100
. Beachten Sie zunächst, dass Sie eine Punktzahl erhalten können, indem Sie nur die Anzahl der Nichtübereinstimmungen zwischen den beiden Zeichenfolgen zählen.
Sie können jede Sprache verwenden, die frei verfügbar und unter Linux einfach zu installieren ist.
Krawattenbruch
Im Falle eines Unentschieden werde ich Ihren Code auf meinem Linux-Computer ausführen und der schnellste Code gewinnt.
for(int i=0;i<=5;i++)
erlaubt, weil es Daten speicherti
?{ uint32_t foo[1000]; for (foo[0] = 0; foo[0] < 5; ++foo[0]) printf("%d ", foo[0]); }
Dies setzt voraus, dass Ihr Array von 32-Bit-Ganzzahlen aufgerufen wirdfoo
.Antworten:
C ++, Punktzahl 92,35
Schätzalgorithmus: Der Algorithmus findet die erste Stelle, an der sich die beiden Zeichenfolgen unterscheiden, und versucht dann alle möglichen N Operationspermutationen (Einfügen, Löschen, Ersetzen - übereinstimmende Zeichen werden übersprungen, ohne eine Operation zu verbrauchen). Jeder mögliche Satz von Operationen wird basierend darauf bewertet, wie weit dieser Satz von Operationen erfolgreich mit den beiden Zeichenfolgen übereinstimmt und wie stark die Zeichenfolgenlängen konvergieren. Nach dem Bestimmen des Satzes von N Operationen mit der höchsten Punktzahl wird die erste Operation in dem Satz angewendet, die nächste Nichtübereinstimmung wird gefunden und der Prozess wird wiederholt, bis das Ende der Zeichenfolge erreicht ist.
Das Programm versucht alle Werte von N von 1 bis 10 und wählt die Stufe aus, die die besten Ergebnisse liefert. N = 10 ist im Allgemeinen das Beste, wenn die Bewertungsmethode die Zeichenfolgenlänge berücksichtigt. Höhere Werte von N wären wahrscheinlich noch besser, würden aber exponentiell länger dauern.
Speichernutzung: Da das Programm rein iterativ ist, benötigt es sehr wenig Speicher. Nur 19 Variablen werden verwendet, um den Programmstatus zu verfolgen. Diese werden durch #defines als globale Variablen festgelegt.
Verwendung: Das Programm wird genauso verwendet wie das von feersum: Der erste Parameter wird als Datei angenommen, und alle zusätzlichen Parameter geben an, dass die Änderungen angezeigt werden sollen. Das Programm druckt immer die geschätzte Bearbeitungsentfernung und die Punktzahl.
Überprüfungsausgabe: Die Überprüfungsausgabe, die in drei Zeilen formatiert wurde:
Die obere Zeile ist die Zielzeichenfolge, die mittlere die Operationen und die untere die zu bearbeitende Zeichenfolge. Leerzeichen in der Operationszeile zeigen an, dass die Zeichen übereinstimmen. 'R' gibt an, dass das Zeichen der Bearbeitungszeichenfolge an dieser Position durch das Zeichen der Zielzeichenfolge ersetzt wird. 'I' gibt an, dass an der Bearbeitungszeichenfolge das Zeichen der Zielzeichenfolge an dieser Position eingefügt ist. 'D' zeigt an, dass das Zeichen an der Bearbeitungszeichenfolge an dieser Position gelöscht wurde. In die Bearbeitungs- und Zielzeichenfolgen werden Leerzeichen eingefügt, wenn in das andere Zeichen ein Zeichen eingefügt oder gelöscht wird, damit sie ausgerichtet werden.
quelle
C ++ 75.0
Das Programm ist für die Arbeit mit beliebigen Textzeichenfolgen ausgelegt. Sie können unterschiedlich lang sein, solange keines mehr als 13824 Zeichen enthält. Es werden 1.897 16-Bit-Ganzzahlen verwendet, was 949 32-Bit-Ganzzahlen entspricht. Zuerst schrieb ich es in C, stellte dann aber fest, dass es keine Funktion zum Lesen einer Zeile gab.
Das erste Befehlszeilenargument sollte ein Dateiname sein. Wenn ein zweites Argument vorhanden ist, wird eine Zusammenfassung der Änderungen gedruckt. Die erste Zeile in der Datei wird ignoriert, während die zweite und dritte die Zeichenfolgen sind.
Der Algorithmus ist eine doppelt blockierte Version des üblichen Algorithmus. Es führt im Grunde die gleiche Anzahl von Operationen aus, ist jedoch natürlich viel weniger genau, da ein Großteil der potenziellen Einsparungen verloren geht, wenn eine gemeinsame Teilsequenz über die Kante eines Blocks aufgeteilt wird.
quelle
Python,
100Ich habe es geschafft, die Bearbeitungsentfernung im zugewiesenen Speicherlimit perfekt zu berechnen. Leider verstößt dieser Eintrag gegen zwei Regeln der Herausforderung, in Buchstaben, wenn nicht im Geiste.
Erstens habe ich meine Daten nicht in 1000 32-Bit-Ints gespeichert. Für Zeichenfolgen mit 10000 Zeichen erstellt mein Programm zwei Arrays mit 10000 Zeichen, die nur +1, 0 oder -1 enthalten. Bei 1,585 Bit pro ternärer Zahl wäre es möglich, diese 20000 Tits in 31700 Bit zu packen, wobei 300 Bit mehr als genug für meine 7 verbleibenden 16-Bit-Ganzzahlen bleiben.
Zweitens habe ich den erforderlichen Modus zum Anzeigen von Änderungen nicht implementiert. Ich habe alternativ einen Modus implementiert, der die vollständige Bearbeitungsmatrix druckt. Es ist absolut möglich, den Bearbeitungspfad aus dieser Matrix zu berechnen, aber ich habe momentan keine Zeit, ihn zu implementieren.
Beispieleingabe:
Beispiel ausführliche Ausgabe:
quelle