Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi "Überlappungen" zwischen zwei Strings (https://www.delphipraxis.net/204641-ueberlappungen-zwischen-zwei-strings.html)

Der schöne Günther 15. Jun 2020 08:24

"Überlappungen" zwischen zwei Strings
 
Mein Covfefe ☕ scheint heute noch nicht zu wirken.

Angenommen ich habe zwei Strings
Delphi-Quellcode:
Eins Zwo Hallo Welt
und
Delphi-Quellcode:
Hallo Welt Guten Tag
. Ich möchte die zwei Strings konkatenieren, allerdings "ohne das doppelte mittendrin":

Code:
Eins Zwo Hallo Welt
         Hallo Welt Guten Tag

=>

Eins Zwo Hallo Welt Guten Tag
Gibt es da einen trivialen Lösungsansatz? Schwere Geschütze mit Queues/Stacks oder regulären Ausdrücken wollte ich vermeiden.

DieDolly 15. Jun 2020 08:54

AW: "Überlappungen" zwischen zwei Strings
 
Ohne das doppelte mitten drin oder allgemein doppelte Wörter?

Gausi 15. Jun 2020 09:21

AW: "Überlappungen" zwischen zwei Strings
 
Auf Anhieb fällt mir nur das naive Vorgehen ein:
  • Suche das erste Zeichen des zweiten Strings im ersten Strings (also im Beispiel "H")
  • Überprüfe, ob ab dieser Stelle der Rest des ersten Strings mit dem Anfang des zweiten übereinstimmt
  • Falls nicht, suche das nächste Vorkommen des ersten Zeichens im zweiten Strings. (*)
  • Falls ja, hat man die Überlappung gefunden und kann die Strings zusammenbauen

(*) diese Stelle kann man ggf. beschleunigen, wenn man ähnliche Tricks anwendet wie bei Knuth-Morris-Pratt. Damit sollte man dann auf eine lineare Worst-Case-Laufzeit kommen, die so erstmal nicht garantiert ist.

Nersgatt 15. Jun 2020 09:34

AW: "Überlappungen" zwischen zwei Strings
 
Wie wäre es, wenn man die Strings übereinander legt und prüft, ob die überlappenden Buchstaben/Teilstring gleich sind. Wenn ja, hat man die Überschneidung. Wenn nein, verschiebt man den 2. String um eine Stelle und prüft wieder. Da böte sich vielleicht eine rekursive Lösung an.

Code:
Eins Zwo Hallo Welt
Hallo Welt Guten Tag

Eins Zwo Hallo Welt
 Hallo Welt Guten Tag

Eins Zwo Hallo Welt
  Hallo Welt Guten Tag

...

Eins Zwo Hallo Welt
         Hallo Welt Guten Tag

Moombas 15. Jun 2020 09:39

AW: "Überlappungen" zwischen zwei Strings
 
Vorab eine blöde Frage:

Kann auch folgendes vorkommen:

1. Eins Zwo Hallo Welt
2. Drei Hallo Guten Tag
= keine Überlappung.

Oder:

1. Eins Zwo Hallo Welt Drei
2. Hallo Welt Guten Tag
= Eins Zwo Hallo Welt Guten Tag Drei

Oder ist es immer so, das der Beginn der möglichen Überlappung am Anfang des zweiten Strings definiert ist?

Der schöne Günther 15. Jun 2020 09:42

AW: "Überlappungen" zwischen zwei Strings
 
Zitat:

Zitat von Moombas (Beitrag 1467282)
Oder ist es immer so, dass der Beginn der möglichen Überlappung am Anfang des zweiten Strings definiert ist?

Ganz genau: Ende von 1 = Anfang 2

Redeemer 15. Jun 2020 09:49

AW: "Überlappungen" zwischen zwei Strings
 
Irgendwie so?
Delphi-Quellcode:
uses Math, StrUtils;

Length1 := Length(Text1); // man sollte LeftStr und RightStr unten ersetzen durch das wesentlich effizientere Copy, wofür man das hier braucht, dafür bin ich aber zu faul
for i := 1 to Min(Length(Text2), Length1) do
if RightStr(Text1, i) = LeftStr(Text2, i) then
Exit(Text1, Copy(Text2, i, High(Integer)));
raise Exception.Create('geht nicht');
Je nach Anforderung muss man die Schleife umdrehen.

Gausi 15. Jun 2020 09:55

AW: "Überlappungen" zwischen zwei Strings
 
Dann würde ich erstmal die Methode von mir (bzw. die von Nersgatt, das ist ja identisch) nehmen. Kann man natürlich in der Hinsicht optimieren, dass das erste "Übereinanderlegen" so anfängt, dass der untere String rechtsbündig mit dem ersten ist. Vorher ergibt die Suche ja keinen Sinn.

Und wenn eine gute (d.h. lineare) Worst-Case-Laufzeit wichtig ist (Probleme machen bei solchen Ansätzen Strings wie "abababababaC"), dann schau dir Knuth-Morris-Pratt an und modifiere den etwas. Das "Muster" wäre dann der zweite String, und die Modifikation muss so sein, dass das Muster auch als "gefunden" gilt, wenn es nach rechts über den "Text" (also der String in dem gesucht wird) herausragt.

"Bruteforce" wäre natürlich eine Schleife mit AnsiStartStr und AnsiEndStr (oder vergleichbaren Ansätzen, siehe Beitrag von Redeemer). Bei kurzen Strings ist das aber sicherlich vertretbar, d.h. wenn die Programmierkosten hier relevanter sind als eine gute Laufzeit. ;-)

Der schöne Günther 15. Jun 2020 10:07

AW: "Überlappungen" zwischen zwei Strings
 
Zitat:

Zitat von Gausi (Beitrag 1467287)
schau dir Knuth-Morris-Pratt an

Vielen Dank an alle, das werde ich tun.

Vorher schaue ich aber ob ich nicht vielleicht doch um den Abgleich drum herum komme 😎

Gausi 15. Jun 2020 10:20

AW: "Überlappungen" zwischen zwei Strings
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1467289)
Vielen Dank an alle, das werde ich tun.

Vielleicht, um das klar zu stellen: KMP ist theoretisch interessant, in der Praxis ist das bei "normalen" Texten eher nicht so wichtig. Diesen Programmieraufwand kann man sich in der Regel sparen, da die problematischen Muster praktisch nie auftreten. Relevant wird das ggf., wenn deine Strings DNA-Sequenzen sind (und somit die Anzahl der verschiedenen Buchstaben sehr gering ist), aber sonst eher nicht.

Habe damals meine Diplomarbeit darüber geschrieben, daher reite ich da manchmal gerne drauf rum. :lol:
Ein kleines Animationsprogramm, was z.B. auch die Anzahl der Vergleiche bei verschiedenen Verfahren ausgibt, gibt es auf meiner Webseite.

Aber wenn ich das nochmal überdenke: Der Boyer-Moore-Ansatz könnte hier (wieder etwas modifiziert) auch funktionieren ... (und der ist leichter zu implementieren, imho).

Moombas 15. Jun 2020 10:25

AW: "Überlappungen" zwischen zwei Strings
 
Ich würde das nicht mal Zeichen genau machen in dem Fall.
Ich würde die Strings splitten und dann Wort für Wort vergleichen so lange es gleich ist.

1. Den ersten String zerteilen (Wortweise)
2. Dies von hinten nach vorne durchgehen und mit dem zweiten String (Wortweise, von vorne nach hinten) vergleichen
3. Sobald das mit den Worten nicht mehr passt, Stelle merken und aus der Schleife aussteigen.
4. Strings zusammenfügen.

Der schöne Günther 15. Jun 2020 10:33

AW: "Überlappungen" zwischen zwei Strings
 
Zitat:

Zitat von Gausi (Beitrag 1467291)
Relevant wird das ggf., wenn deine Strings DNA-Sequenzen sind

Und ich dachte immer das wird so gemacht:
https://xkcd.com/2298/


Zitat:

Zitat von Moombas (Beitrag 1467292)
Ich würde die Strings splitten und dann Wort für Wort vergleichen so lange es gleich ist

Ja, das würde ich tun. Bei sind es wirklich "Worte" die immer durch das gleiche Zeichen getrennt wären. Danke 👍

joachimd 15. Jun 2020 12:07

AW: "Überlappungen" zwischen zwei Strings
 
ich würde den ersten string von hinten und den zweiten von vorne nehmen - ich weiss, hört sich jetzt schweinisch an ;)

1. Erstes Zeichen vom zweiten String unter letztes Zeichen vom ersten legen
2. Überlappung vergleichen
3. Bei Gleichheit zweiten String um eines nach vorne schieben, goto 2
4. Bei Ungleichheit hat man den überlappenden Teil gefunden

Gausi 15. Jun 2020 12:17

AW: "Überlappungen" zwischen zwei Strings
 
Zitat:

Zitat von joachimd (Beitrag 1467312)
ich würde den ersten string von hinten und den zweiten von vorne nehmen - ich weiss, hört sich jetzt schweinisch an ;)

1. Erstes Zeichen vom zweiten String unter letztes Zeichen vom ersten legen
2. Überlappung vergleichen
3. Bei Gleichheit zweiten String um eines nach vorne schieben, goto 2
4. Bei Ungleichheit hat man den überlappenden Teil gefunden

Damit findest du aber ggf. nicht die komplette Überlappung.
Deine Methode würde in diesem Beispiel nur "ei" als Überlappung finden, denn der folgende Schleifendurchlauf mit "rei" und "ein" sorgt für den Abbruch.

Gewünscht wäre aber vermutlich "eins zwei drei".
Code:
ich zähle eins zwei drei
                      eins zwei drei wurde gezählt
Auch wenn das gekünstelt ist und die "Wortbedingung" hier auch verletzt ist. ;-)

Edit: bzw. würde man gar keine Überlappung finden, weil schon "i" und "e" ungleich sind.

Uwe Raabe 15. Jun 2020 13:51

AW: "Überlappungen" zwischen zwei Strings
 
Mit TStringHelper geht das recht überschaubar:
Delphi-Quellcode:
function ConcatNoOverlap(const A, B: string): string;
var
  I: Integer;
begin
  for I := Min(A.Length, B.Length) downto 1 do
    if string.Compare(A, A.Length - I, B, 0, I) = 0 then
      Exit(A.Remove(I-1) + B);
  Result := A + B;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:00 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz