Ihre Aufgabe ist es, das Problem der längsten gemeinsamen Folge für n Zeichenfolgen mit einer Länge von 1000 zu lösen .
Eine gültige Lösung für das LCS-Problem für zwei oder mehr Zeichenfolgen S 1 ,… S n ist eine beliebige Zeichenfolge T mit maximaler Länge, so dass die Zeichen von T in allen S i in derselben Reihenfolge wie in T erscheinen .
Beachten Sie, dass T nicht Teil sein muss Zeichenfolge von S i .
Wir haben dieses Problem bereits in kürzester Zeit gelöst . Diesmal spielt die Größe keine Rolle.
Beispiel
Die Strings axbycz
und xaybzc
haben 8 gemeinsame Teilsequenzen der Länge 3:
abc abz ayc ayz xbc xbz xyc xyz
All dies wäre eine gültige Lösung für das LCS-Problem.
Einzelheiten
Schreiben Sie ein vollständiges Programm, das das LCS-Problem wie oben erläutert löst und dabei die folgenden Regeln einhält:
Die Eingabe besteht aus zwei oder mehr Zeichenfolgen der Länge 1000, die aus ASCII-Zeichen mit Codepunkten zwischen 0x30 und 0x3F bestehen.
Sie müssen die Eingabe von STDIN lesen.
Sie haben zwei Möglichkeiten für das Eingabeformat:
Auf jede Zeichenfolge (einschließlich der letzten) folgt ein Zeilenvorschub.
Die Saiten sind ohne Trennzeichen und ohne nachlaufenden Zeilenvorschub miteinander verkettet.
Die Anzahl der Zeichenfolgen wird als Befehlszeilenparameter an Ihr Programm übergeben.
Sie müssen die Ausgabe, dh eine der gültigen Lösungen für das LCS, in STDOUT schreiben, gefolgt von einem Zeilenvorschub.
Ihre bevorzugte Sprache muss einen kostenlosen Compiler / Interpreter (wie in Bier) für mein Betriebssystem (Fedora 21) haben.
Wenn Sie Compiler-Flags oder einen bestimmten Interpreter benötigen, erwähnen Sie dies bitte in Ihrem Beitrag.
Wertung
Ich werde Ihren Code mit 2, 3 usw. Zeichenfolgen ausführen, bis das Drucken einer gültigen Lösung länger als 120 Sekunden dauert. Dies bedeutet, dass Sie für jeden Wert von n 120 Sekunden Zeit haben .
Die höchste Anzahl von Zeichenfolgen, für die Ihr Code rechtzeitig fertiggestellt wurde, ist Ihre Punktzahl.
Bei einem Gleichstand von n wird die Einsendung, die das Problem für n Strings in kürzester Zeit gelöst hat , zum Gewinner erklärt.
Alle Einsendungen werden auf meinem Computer zeitgesteuert (Intel Core i7-3770, 16 GiB RAM, kein Swap).
Die n Zeichenfolgen des (n-1) -ten Tests werden durch Aufrufen rand n
(und Entfernen der Zeilenvorschübe, falls erforderlich) generiert , wobei rand
Folgendes definiert ist:
rand()
{
head -c$[500*$1] /dev/zero |
openssl enc -aes-128-ctr -K 0 -iv $1 |
xxd -c500 -ps |
tr 'a-f' ':-?'
}
Der Schlüssel befindet sich 0
im obigen Code, aber ich behalte mir das Recht vor, ihn in einen nicht genannten Wert zu ändern, wenn ich den Verdacht habe, dass jemand die Ausgabe (teilweise) fest codiert.
quelle
public static void main(...)
?Antworten:
C, n = 3 in ~ 7 Sekunden
Algorithmus
Der Algorithmus ist eine direkte Verallgemeinerung der Standardlösung für die dynamische Programmierung auf
n
Sequenzen. Für 2 ZeichenfolgenA
undB
sieht die Standardwiederholung folgendermaßen aus:Für 3 - Strings
A
,B
,C
ich benutze:Der Code implementiert diese Logik für beliebige Werte von
n
.Effizienz
Die Komplexität meines Codes ist O (s ^ n) mit
s
der Länge der Zeichenfolgen. Basierend auf dem, was ich gefunden habe, sieht es so aus, als ob das Problem NP-vollständig ist. Während der veröffentlichte Algorithmus für größere Werte von sehr ineffizient istn
, ist es möglicherweise nicht möglich, massiv bessere Ergebnisse zu erzielen. Das einzige, was ich gesehen habe, sind einige Ansätze, die die Effizienz kleiner Alphabete verbessern. Da das Alphabet hier mäßig klein ist (16), könnte dies zu einer Verbesserung führen. Ich gehe immer noch davon aus, dass niemand eine legitime Lösung finden wird, die höher alsn = 4
in 2 Minuten ist undn = 4
bereits ehrgeizig aussieht.Ich habe die Speichernutzung in der ersten Implementierung reduziert, damit sie
n = 4
genügend Zeit benötigt. Es wurde jedoch nur die Länge der Sequenz erzeugt, nicht die Sequenz selbst. Überprüfen Sie den Versionsverlauf dieses Beitrags, um diesen Code zu sehen.Code
Da Schleifen über n-dimensionale Matrizen mehr Logik erfordern als feste Schleifen, verwende ich eine feste Schleife für die niedrigste Dimension und verwende nur die generische Schleifenlogik für die verbleibenden Dimensionen.
Anleitung zum Laufen
Laufen:
lcs.c
.Kompilieren Sie mit hohen Optimierungsoptionen. Ich benutzte:
Unter Linux würde ich versuchen:
Führen Sie 2 bis 4 Sequenzen als Befehlszeilenargumente aus:
Geben Sie bei Bedarf die Befehlszeilenargumente in einfache Anführungszeichen an, da das für die Beispiele verwendete Alphabet Shell-Sonderzeichen enthält.
Ergebnisse
test2.sh
undtest3.sh
sind die Testsequenzen von Dennis. Ich kenne die richtigen Ergebnisse nicht, aber die Ausgabe sieht zumindest plausibel aus.quelle
N_MAX
als Makro definieren und das Compiler-Flag hinzufügen-std=c99
, um Ihren Code mit GCC zu kompilieren.Diese Antwort ist derzeit aufgrund eines Fehlers fehlerhaft. Bald behoben ...
C, 2 Saiten in ~ 35 SekundenDies ist eine sehr laufende Arbeit (wie die schreckliche Unordnung zeigt), aber hoffentlich löst sie einige gute Antworten aus!
Der Code:
Die relevante Funktion, die die gesamte LCS-Berechnung ausführt, ist die Funktion
LCS
. Der obige Code wird einen eigenen Aufruf dieser Funktion zeitlich festlegen.Speichern unter
main.c
und kompilieren mit:gcc -Ofast main.c -o FLCS
Der Code kann entweder mit Befehlszeilenargumenten oder über stdin ausgeführt werden. Bei Verwendung von stdin werden mehrere Zeichenfolgen erwartet, gefolgt von den Zeichenfolgen selbst.
Oder:
Auf einer Mac OS X-Box mit einem 1,7 GHz Intel Core i7 und dem von Dennis bereitgestellten Testfall erhalten wir die folgende Ausgabe für 2 Zeichenfolgen:
Der Ansatz ist meinem Ansatz für die frühere Herausforderung hier sehr ähnlich . Zusätzlich zur vorherigen Optimierung überprüfen wir jetzt bei jeder Rekursion die Gesamtzahl der gemeinsam genutzten Zeichen zwischen Zeichenfolgen und beenden sie vorzeitig, wenn es keine Möglichkeit gibt, einen längeren Teilstring als den bereits vorhandenen zu erhalten.
Im Moment verarbeitet es 2 Saiten in Ordnung, neigt aber dazu, bei mehr zum Absturz zu kommen. Weitere Verbesserungen und eine bessere Erklärung folgen!
quelle