Dynamische Programmierung für string schneiden
Arbeite ich auf Folgendes problem aus dieser buchen.
Einer bestimmten string-processing-Sprache bietet eine primitive operation, die zerlegt eine Zeichenkette in zwei Teile. Da dieser Vorgang umfasst das kopieren der original-string, dauert es n Zeiteinheiten für einen string der Länge n, unabhängig von der Lage des Schnittes. Angenommen, jetzt, dass Sie zu brechen einen string in viele Stücke. Die Reihenfolge, in der die Pausen gemacht werden, kann das Auswirkungen auf die gesamte Laufzeit. Zum Beispiel, wenn Sie möchten, schneiden Sie ein 20-Zeichen-string an den Positionen 3 und 10, dann machen Sie den ersten Schnitt an position 3 entstehen insgesamt Kosten von 20+17=37, während Sie die position 10 hat ein besseres Preis von 20+10=30.
Ich brauche einen dynamischen Programmier-Algorithmus, gegeben m schneidet, findet die minimale Kosten für das schneiden eines string in m+1 Teile.
- Ich verstehe nicht, Ihre Erklärung von Kosten der Zeichenfolge. Können Sie mir sagen, wie hast du
20+17
und20+10
? - eine noch optimalere Lösung würde bedeuten, dass ein dynamischer Algorithmus ausgeführt, eine Konstante Zeit von n unabhängig von m, das wäre noch effizienter. Nur so ein Gedanke.
- für 20+17, 20 ist von Kosten für die Schnittlängen 3 und 17 ist vom Wert der Schnittlänge 20-3 = 17.
- Das wirft eine weitere Frage. Ist der zweite oder spätere schneiden relativ zum bisherigen abschneiden? Beispiel, wenn Ihre
3 and 10
den ersten3rd
position geschnitten wird und dann 17 bleibt und dann10th
position geschnitten (aber mit Bezug auf ursprüngliches Wort13th
geschnitten)?? - Die Schneid-Positionen stehen fest.
- Nebenbei: gibt es eine andere (benannte) problem, das ist äquivalent zu dieser, und zu deren Lösung die hier angewendet werden? Ich bin sicher, es ist, ich kann einfach nicht daran zu denken.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den divide and conquer Ansatz scheint mir der beste für diese Art von problem. Hier ist eine Java-Implementierung des Algorithmus:
Hinweis: array
m
sollten in aufsteigender Reihenfolge sortiert werden (verwenden SieArrays.sort(m);
)Beispiel :
Drucken
30
** Bearbeiten **
Implementierte ich zwei andere Methoden zu beantworten, das problem in die Frage.
1. Median-cut-approximation
Diese Methode cut rekursiv immer der größte Brocken. Die Ergebnisse sind nicht immer die beste Lösung, bietet aber einen nicht zu vernachlässigenden Gewinn (in der Größenordnung von +100000% Gewinn aus meinen tests) für eine vernachlässigbar minimale Schnitt-Verlust Differenz aus den besten Kosten.
2. Eine Konstante Zeit multi-cut
Statt Berechnung die minimalen Kosten, nur verwenden verschiedene Indizes und Puffer. Da diese Methode führt in konstanter Zeit, es gibt immer n. Plus, die Methode eigentlich split die Zeichenfolge in Teilzeichenfolgen.
Hinweis: dass diese Letzte Methode könnte leicht geändert werden, um zu akzeptieren
String str
argument stattn
- und set -n = str.length()
, und geben Sie einenString[]
array voncharArr[][]
.findMinCutCost2
?? LOLFür die dynamische Programmierung, ich behaupte, dass alles, was Sie wirklich wissen müssen ist, was der Staat soll Raum sein - wie stellen teilweise Probleme.
Hier teilen wir einen string in m+1 Teile durch die Schaffung neuer bricht. Ich behaupte, dass ein guter Zustand der Raum ist eine Menge von (a, b) - Paaren, wobei a die Position des anfangs eines Zeichens und b ist die Position des Endes der gleiche Teilstring, gezählt als Anzahl der Pausen in der final kaputten string. Die Kosten für jedes paar ist die minimalen Kosten von breaking it up. Wenn b <= a + 1, dann sind die Kosten 0, da es keine mehr Pausen zu setzen. Wenn b größer ist, dann werden die möglichen Standorte für die nächste Pause, die Teilstring sind die Punkte a+1, a+2,... b-1. Die nächste Pause ist wird Kosten, b-a, unabhängig davon, wo wir es, aber wenn wir es an position k die minimalen Kosten, die später bricht, ist (a, k) + (k, b).
So, um dieses Problem zu lösen, die mit der dynamischen Programmierung, den Aufbau einer Tabelle (a, b) der minimale Kosten, wo Sie arbeiten können Sie die Kosten für die Pausen auf den Saiten mit k Abschnitten durch Betrachtung von k - 1 mögliche Pausen und dann nach den Kosten des strings mit höchstens k - 1 Abschnitte.
Einer Weise zu erweitern wäre, zu beginnen, indem Sie erstellen eine Tabelle T[a, b] und setzen alle Einträge in dieser Tabelle zur Unendlichkeit. Gehen Sie dann über der Tabelle wieder und wo b <= a+1 setzen T[a,b] = 0. Dieser füllt die Einträge darstellt Abschnitte der ursprünglichen Zeichenfolge, die keine weiteren Kürzungen. Scannen Sie jetzt durch die Tabelle und für die einzelnen T[a,b] mit b > a + 1 betrachten Sie jede mögliche k so, dass a < k < b und wenn min_k ((Länge zwischen den Pausen a und b) + T[a,k] + T[k,b]) < T[a,b] die Menge T[a,b] das minimum-Wert. Diese erkennt, wo Sie jetzt wissen, einen Weg zu hacken, bis die Teilfolgen vertreten durch T[a,k] und T[k,b] Billig, so dass dies gibt Ihnen eine bessere Weise zu hacken, T[a,b]. Wenn Sie jetzt wiederholen Sie diese m Zeiten, die Sie fertig sind - verwenden Sie eine standard-dynamische Programmierung backtrack die Lösung erarbeiten. Es könnte helfen, wenn Sie speichern Sie die besten Wert von k für jedes T[a,b] in eine separate Tabelle.
python-code:
Hier ist eine c++ Implementierung. Seine ein O(n^3) - Umsetzung D. P . Unter der Annahme, dass die cut-array ist sortiert . Wenn es nicht ist, dauert es O(n^3) Zeit zum Sortieren er daher asymptotische Zeitkomplexität bleibt gleich.