<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://wiki-de.moshellshocker.dns64.de/index.php?action=history&amp;feed=atom&amp;title=Hirschberg-Algorithmus</id>
	<title>Hirschberg-Algorithmus - Versionsgeschichte</title>
	<link rel="self" type="application/atom+xml" href="https://wiki-de.moshellshocker.dns64.de/index.php?action=history&amp;feed=atom&amp;title=Hirschberg-Algorithmus"/>
	<link rel="alternate" type="text/html" href="https://wiki-de.moshellshocker.dns64.de/index.php?title=Hirschberg-Algorithmus&amp;action=history"/>
	<updated>2026-05-27T06:32:31Z</updated>
	<subtitle>Versionsgeschichte dieser Seite in Wikipedia (Deutsch) – Lokale Kopie</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>https://wiki-de.moshellshocker.dns64.de/index.php?title=Hirschberg-Algorithmus&amp;diff=391173&amp;oldid=prev</id>
		<title>imported&gt;Invisigoth67: typo</title>
		<link rel="alternate" type="text/html" href="https://wiki-de.moshellshocker.dns64.de/index.php?title=Hirschberg-Algorithmus&amp;diff=391173&amp;oldid=prev"/>
		<updated>2024-09-25T14:01:50Z</updated>

		<summary type="html">&lt;p&gt;typo&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Neue Seite&lt;/b&gt;&lt;/p&gt;&lt;div&gt;Der &amp;#039;&amp;#039;&amp;#039;Hirschberg-Algorithmus&amp;#039;&amp;#039;&amp;#039; berechnet das paarweise [[Sequenzalignment]] und hat einen zur Eingabe [[Platzkomplexität|linearen Speicherbedarf]]. Der in den 1970er Jahren von [[Dan Hirschberg]] entwickelte [[Algorithmus]] verwendet die Methode der [[Dynamische Programmierung|Dynamischen Programmierung]] und das [[Teile und herrsche (Informatik)|Divide-and-conquer]] Prinzip.&lt;br /&gt;
&lt;br /&gt;
== Allgemeines ==&lt;br /&gt;
&lt;br /&gt;
Der Hirschberg-Algorithmus ist ein allgemein einsetzbarer und optimaler Algorithmus zum Auffinden eines Sequenzalignment. Der bekannte [[BLAST-Algorithmus]] und der [[FASTA-Algorithmus]] sind nur suboptimale Heuristiken. Vergleicht man den Hirschberg-Algorithmus mit dem [[Needleman-Wunsch-Algorithmus]], so handelt es sich beim Hirschberg-Algorithmus weniger um einen komplett neuen Algorithmus, sondern eher um eine clevere Strategie, die den Needleman-Wunsch-Algorithmus geschickt einsetzt, um den Speicherverbrauch zu&lt;br /&gt;
linearisieren, was auch das Besondere an diesem Algorithmus ist: Die Berechnungen für ein Sequenzalignment benötigen nur linear viel Speicherplatz, womit die [[Platzkomplexität]] des Algorithmus in [[O-Notation|O]](n) liegt. Zur Berechnung eines Alignments zweier Zeichenketten &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; und &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;&lt;br /&gt;
mit &amp;lt;math&amp;gt;m=|x|&amp;lt;/math&amp;gt; und &amp;lt;math&amp;gt;n=|y|&amp;lt;/math&amp;gt;  besitzt der Algorithmus eine Laufzeit&lt;br /&gt;
von &amp;lt;math&amp;gt;\Theta(m n)&amp;lt;/math&amp;gt; und einen Speicherverbrauch von &amp;lt;math&amp;gt;\Theta(\min\{m,n\})&amp;lt;/math&amp;gt;. O.B.d.A soll im Folgenden &amp;lt;math&amp;gt;n\leq m&amp;lt;/math&amp;gt; gelten, so dass der Platzbedarf in &amp;lt;math&amp;gt;\Theta(n)&amp;lt;/math&amp;gt; liegt.&lt;br /&gt;
&lt;br /&gt;
Anwendung findet der Algorithmus zum Beispiel in der [[Bioinformatik]] zum Abgleich verschiedener [[Desoxyribonukleinsäure|DNA]]- oder [[Protein]]sequenzen.&lt;br /&gt;
&lt;br /&gt;
In einer leicht abgewandelten Form wird Hirschbergs Algorithmus auch dazu verwendet, um in einem [[Graph (Graphentheorie)|Graphen]] parallel [[Zusammenhang von Graphen|Zusammenhangskomponenten]] mit Aufwand &amp;lt;math&amp;gt;\Theta(\log^2 n)&amp;lt;/math&amp;gt; auf &amp;lt;math&amp;gt;\Theta(n^2)&amp;lt;/math&amp;gt; Prozessoren zu berechnen.&lt;br /&gt;
&lt;br /&gt;
=== Berechnung der Levenshtein-Distanz auf linearem Speicherplatz ===&lt;br /&gt;
&lt;br /&gt;
Zum Verständnis des Hirschberg-Algorithmus ist es zunächst wichtig zu verstehen, dass sich die [[Levenshtein-Distanz]] auf linearem Speicherplatz berechnen lässt:&lt;br /&gt;
&lt;br /&gt;
 01 &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt; := 0&lt;br /&gt;
 02 for j in 1..n loop&lt;br /&gt;
 03       &amp;lt;math&amp;gt;T_j&amp;lt;/math&amp;gt; := &amp;lt;math&amp;gt;T_{j-1}&amp;lt;/math&amp;gt; + &amp;lt;math&amp;gt;Ins(y_j)&amp;lt;/math&amp;gt;&lt;br /&gt;
 04 end loop&lt;br /&gt;
 05 for i in 1..m loop&lt;br /&gt;
 06       s := &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;&lt;br /&gt;
 07       &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt; := &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt; + &amp;lt;math&amp;gt;Del(x_i)&amp;lt;/math&amp;gt;&lt;br /&gt;
 08       c := &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;&lt;br /&gt;
 09       for j in 1..n loop&lt;br /&gt;
 10             c := &amp;lt;math&amp;gt;\min\begin{cases}s&amp;amp;+Sub(x_i,y_j)\\ T_j&amp;amp;+Del(x_i)\\c&amp;amp;+Ins(y_j)\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
 11             s := &amp;lt;math&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
 12             &amp;lt;math&amp;gt;T_j&amp;lt;/math&amp;gt; := c&lt;br /&gt;
 13       end loop&lt;br /&gt;
 14 end loop&lt;br /&gt;
&lt;br /&gt;
In den Zeilen 1–4 wird das eindimensionale Feld &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; mit n Plätzen Speicherbedarf initialisiert. In Zeile 6 wird die Initialisierung des ersten Elements &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt; in &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; gerettet.&lt;br /&gt;
Danach wird &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt; und &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; mit dem Startwert für die nächste Zeile initialisiert. Die nachfolgende Abbildung zeigt eine Momentaufnahme eines Zeilendurchlaufs.&lt;br /&gt;
In der inneren Schleife zeigt &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; immer auf das jeweils zuvor berechnete Ergebnis, während &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; das noch benötigte Ergebnis der letzten Zeile sichert. Nach Zeile 14&lt;br /&gt;
steht die [[Levenshtein-Distanz]] als Ergebnis in &amp;lt;math&amp;gt;T_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
   &amp;#039;&amp;#039;&amp;#039;ε &amp;lt;math&amp;gt;y_1&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;y_2&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;y_3&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;y_4&amp;lt;/math&amp;gt; ...&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
 &amp;#039;&amp;#039;&amp;#039;ε&amp;#039;&amp;#039;&amp;#039;    &amp;lt;span style=&amp;quot;color:#00FF00;&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;  1  2  3  ...&lt;br /&gt;
 &amp;#039;&amp;#039;&amp;#039;&amp;lt;math&amp;gt;x_1&amp;lt;/math&amp;gt;&amp;#039;&amp;#039;&amp;#039;   &amp;lt;span style=&amp;quot;color:#FF00FF;&amp;quot;&amp;gt;1&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;#039;&amp;#039;&amp;#039;&amp;lt;math&amp;gt;x_2&amp;lt;/math&amp;gt;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
 &amp;#039;&amp;#039;&amp;#039;...&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
 s = &amp;lt;span style=&amp;quot;color:#00FF00;&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&lt;br /&gt;
 c = &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt; = &amp;lt;span style=&amp;quot;color:#FF00FF;&amp;quot;&amp;gt;1&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sollte klar sein, dass sich diese Berechnung auch rückwärts durchführen lässt. Dabei wird die gedachte Matrix nicht von links nach rechts und von oben nach unten durchlaufen, sondern von rechts unten nach links oben:&lt;br /&gt;
&lt;br /&gt;
 01 &amp;lt;math&amp;gt;T_n&amp;lt;/math&amp;gt; := 0&lt;br /&gt;
 02 for j in n-1..0 loop&lt;br /&gt;
 03       &amp;lt;math&amp;gt;T_j&amp;lt;/math&amp;gt; := &amp;lt;math&amp;gt;T_{j+1}&amp;lt;/math&amp;gt; + &amp;lt;math&amp;gt;Ins(y_{j+1})&amp;lt;/math&amp;gt;&lt;br /&gt;
 04 end loop&lt;br /&gt;
 05 for i in m-1..0 loop&lt;br /&gt;
 06       s := &amp;lt;math&amp;gt;T_n&amp;lt;/math&amp;gt;&lt;br /&gt;
 07       &amp;lt;math&amp;gt;T_n&amp;lt;/math&amp;gt; := &amp;lt;math&amp;gt;T_n&amp;lt;/math&amp;gt; + &amp;lt;math&amp;gt;Del(x_{i+1})&amp;lt;/math&amp;gt;&lt;br /&gt;
 08       c := &amp;lt;math&amp;gt;T_n&amp;lt;/math&amp;gt;&lt;br /&gt;
 09       for j in n-1..0 loop&lt;br /&gt;
 10             c := &amp;lt;math&amp;gt;\min\begin{cases}s&amp;amp;+Sub(x_{i+1},y_{j+1})\\T_j&amp;amp;+Del(x_{i+1})\\c&amp;amp;+Ins(y_{j+1})\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
 11             s := &amp;lt;math&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
 12             &amp;lt;math&amp;gt;T_j&amp;lt;/math&amp;gt; := c&lt;br /&gt;
 13       end loop&lt;br /&gt;
 14 end loop&lt;br /&gt;
&lt;br /&gt;
=== Berechnung des Alignments auf linearem Speicherplatz ===&lt;br /&gt;
Der Divide-&amp;amp;-Conquer-Algorithmus von &amp;#039;&amp;#039;&amp;#039;Hirschberg&amp;#039;&amp;#039;&amp;#039; berechnet ein Alignment der Zeichenketten &amp;lt;math&amp;gt;|x|&amp;lt;/math&amp;gt; und &amp;lt;math&amp;gt;|y|&amp;lt;/math&amp;gt;, indem er Vorwärts- und Rückwärtsdurchlauf miteinander kombiniert (Zeilenangaben beziehen sich auf den&lt;br /&gt;
nachfolgend angegebenen Pseudocode):&lt;br /&gt;
&lt;br /&gt;
1. Wenn &amp;lt;math&amp;gt;|x|=1&amp;lt;/math&amp;gt; oder &amp;lt;math&amp;gt;|y|=1&amp;lt;/math&amp;gt; liegt ein &amp;#039;&amp;#039;triviales Alignment-Problem&amp;#039;&amp;#039; vor (Zeilen 14 – 22). Ein String bestehend aus nur einem Zeichen muss auf einen anderen String ausgerichtet werden und ein Alignment wird zurückgegeben. Ist &amp;lt;math&amp;gt;|x|&amp;gt;1&amp;lt;/math&amp;gt; und &amp;lt;math&amp;gt;|y|&amp;gt;1&amp;lt;/math&amp;gt; geht man über zu Schritt 2.&lt;br /&gt;
&lt;br /&gt;
2. Ein &amp;#039;&amp;#039;&amp;#039;Vorwärtsdurchlauf&amp;#039;&amp;#039;&amp;#039; berechnet ein Alignment von &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; und der &amp;#039;&amp;#039;&amp;#039;ersten&amp;#039;&amp;#039;&amp;#039; Hälfte von &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; (Zeilen 27 – 40). Das Ergebnis des Vorwärtsdurchlaufs ist ein Feld &amp;lt;math&amp;gt;T^\ell&amp;lt;/math&amp;gt;, dessen Elemente die Kosten für einen Durchlauf von &amp;lt;math&amp;gt;(0,0)&amp;lt;/math&amp;gt; bis &amp;lt;math&amp;gt;(|x|/2, j)&amp;lt;/math&amp;gt; (mit &amp;lt;math&amp;gt;0\leq j\leq n&amp;lt;/math&amp;gt;) angeben.&lt;br /&gt;
&lt;br /&gt;
3. Ein &amp;#039;&amp;#039;&amp;#039;Rückwärtsdurchlauf&amp;#039;&amp;#039;&amp;#039; berechnet ein Alignment von &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; mit der &amp;#039;&amp;#039;&amp;#039;zweiten&amp;#039;&amp;#039;&amp;#039; Hälfte von &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; (Zeilen 42 – 55). Das Ergebnis ist ein weiteres Feld &amp;lt;math&amp;gt;T^r&amp;lt;/math&amp;gt;, dessen Elemente die Kosten für einen Durchlauf von &amp;lt;math&amp;gt;(n,m)&amp;lt;/math&amp;gt; zurück zu &amp;lt;math&amp;gt;(|x|/2, j)&amp;lt;/math&amp;gt; angeben.&lt;br /&gt;
&lt;br /&gt;
4. In den Feldelementen &amp;lt;math&amp;gt;T^\ell(n)&amp;lt;/math&amp;gt; und &amp;lt;math&amp;gt;T^r(0)&amp;lt;/math&amp;gt; stehen die beiden [[Levenshtein-Distanz]]en für die globalen Alignments von &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; und den jeweiligen Hälften von &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;. In den restlichen Elementen von &amp;lt;math&amp;gt;T^\ell&amp;lt;/math&amp;gt; stehen die Distanzen von der ersten &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;-Hälfte zu allen Präfixen von &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;. Entsprechend enthalten die restlichen Elemente von &amp;lt;math&amp;gt;T^r&amp;lt;/math&amp;gt; die Distanzen von der zweiten &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;-Hälfte zu allen Suffixen von &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
5. Die [[Levenshtein-Distanz]] von &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; zu &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; kann nun errechnet werden, indem man entlang der mittleren Zeile der Alignment-Matrix läuft und nach einer kleinsten Summe von korrespondierenden &amp;lt;math&amp;gt;T^\ell&amp;lt;/math&amp;gt;- und &amp;lt;math&amp;gt;T^r&amp;lt;/math&amp;gt;-Elementen sucht. Ist eine solche minimale Summe gefunden, hat man eine Position in der mittleren Zeile gefunden, in der das optimale Alignment die mittlere Zeile bzw. die Mitte von &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; schneidet. An dieser Stelle wird &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; in zwei Teile zerteilt und damit kann auch das Alignment-Problem in zwei kleinere Alignment-Probleme zerteilt werden (Zeilen 59 – 65).&lt;br /&gt;
&lt;br /&gt;
6. Schritt 1 wird rekursiv auf den beiden Teilen von &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; und &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; aufgerufen. Die beiden rekursiven Aufrufe geben Teil-Alignments zurück, die zu einem einzigen Alignment verknüpft werden. Das Alignment wird zurückgegeben (Zeilen 68 und 69).&lt;br /&gt;
&lt;br /&gt;
 01 --&lt;br /&gt;
 02 -- Der &amp;#039;&amp;#039;Divide-&amp;amp;-Conquer&amp;#039;&amp;#039;-Algorithmus von Hirschberg zur&lt;br /&gt;
 03 -- Berechnung des globalen Alignments auf linearem Speicher.&lt;br /&gt;
 04 --&lt;br /&gt;
 05 -- Bei &amp;lt;math&amp;gt;m=|x|,n=|y|,n \leq m&amp;lt;/math&amp;gt; besitzt der Algorithmus eine Laufzeit von &amp;lt;math&amp;gt;\Theta(nm)&amp;lt;/math&amp;gt;&lt;br /&gt;
 06 -- und einen Speicherverbrauch von &amp;lt;math&amp;gt;\Theta(n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
 07 --&lt;br /&gt;
 08 function HirschbergAlignment(x,y : string) return A is&lt;br /&gt;
 09        function SubAlignment(&amp;lt;math&amp;gt;i_1&amp;lt;/math&amp;gt;,&amp;lt;math&amp;gt;j_1&amp;lt;/math&amp;gt;,&amp;lt;math&amp;gt;i_2&amp;lt;/math&amp;gt;,&amp;lt;math&amp;gt;j_2&amp;lt;/math&amp;gt; : integer) return A is&lt;br /&gt;
 10                mitte,cut : integer&lt;br /&gt;
 11                s,c : real&lt;br /&gt;
 12                &amp;lt;math&amp;gt;T^\ell,T^r&amp;lt;/math&amp;gt; : array(&amp;lt;math&amp;gt;j_1&amp;lt;/math&amp;gt;..&amp;lt;math&amp;gt;j_2&amp;lt;/math&amp;gt;) of real&lt;br /&gt;
 13        begin&lt;br /&gt;
 14                if &amp;lt;math&amp;gt;i_1+1=i_2&amp;lt;/math&amp;gt; or &amp;lt;math&amp;gt;j_1=j_2&amp;lt;/math&amp;gt; then&lt;br /&gt;
 15                        -- Konstruiere Matrix T für die Teil-Strings&lt;br /&gt;
 16                        -- x(&amp;lt;math&amp;gt;i_1+1&amp;lt;/math&amp;gt;..&amp;lt;math&amp;gt;i_2&amp;lt;/math&amp;gt;) und y(&amp;lt;math&amp;gt;j_1+1&amp;lt;/math&amp;gt;..&amp;lt;math&amp;gt;j_2&amp;lt;/math&amp;gt;)&lt;br /&gt;
 17                        -- Achtung: Nur linearer Speicherplatz erforderlich!&lt;br /&gt;
 18                        T := ...&lt;br /&gt;
 19                        -- Berechne &amp;#039;&amp;#039;triviales&amp;#039;&amp;#039; Alignment auf Matrix T&lt;br /&gt;
 20                        -- in linearer Laufzeit&lt;br /&gt;
 21                        return Alignment(T,x(&amp;lt;math&amp;gt;i_1+1&amp;lt;/math&amp;gt;..&amp;lt;math&amp;gt;i_2&amp;lt;/math&amp;gt;),y(&amp;lt;math&amp;gt;j_1+1&amp;lt;/math&amp;gt;..&amp;lt;math&amp;gt;j_2&amp;lt;/math&amp;gt;))&lt;br /&gt;
 22                end if&lt;br /&gt;
 23&lt;br /&gt;
 24                mitte := &amp;lt;math&amp;gt;(i_1+i_2)/2&amp;lt;/math&amp;gt;&lt;br /&gt;
 25                -- finde ausgehend &amp;#039;&amp;#039;&amp;#039;von&amp;#039;&amp;#039;&amp;#039; &amp;lt;math&amp;gt;(i_1,j_1)&amp;lt;/math&amp;gt; den minimalen Pfad&lt;br /&gt;
 26                -- mit dem Vorwärtsalgorithmus:&lt;br /&gt;
 27                &amp;lt;math&amp;gt;T^\ell(j_1)&amp;lt;/math&amp;gt; := 0&lt;br /&gt;
 28                for j in &amp;lt;math&amp;gt;j_1+1&amp;lt;/math&amp;gt;..&amp;lt;math&amp;gt;j_2&amp;lt;/math&amp;gt; loop&lt;br /&gt;
 29                        &amp;lt;math&amp;gt;T^\ell(j)&amp;lt;/math&amp;gt; := &amp;lt;math&amp;gt;T^\ell(j-1) + Ins(y_j)&amp;lt;/math&amp;gt;&lt;br /&gt;
 30                end loop&lt;br /&gt;
 31                for i in &amp;lt;math&amp;gt;i_1+1&amp;lt;/math&amp;gt;..mitte loop&lt;br /&gt;
 32                        s := &amp;lt;math&amp;gt;T^\ell(j_1)&amp;lt;/math&amp;gt;&lt;br /&gt;
 33                        c := &amp;lt;math&amp;gt;T^\ell(j_1) + Del(x_i)&amp;lt;/math&amp;gt;&lt;br /&gt;
 34                        &amp;lt;math&amp;gt;T^\ell(j_1)&amp;lt;/math&amp;gt; := c&lt;br /&gt;
 35                        for j in &amp;lt;math&amp;gt;j_1+1&amp;lt;/math&amp;gt;..&amp;lt;math&amp;gt;j_2&amp;lt;/math&amp;gt; loop&lt;br /&gt;
 36                                c := &amp;lt;math&amp;gt;\min\begin{cases}T^\ell(j)&amp;amp;+Del(x_i)\\s&amp;amp;+Sub(x_i,y_j)\\c&amp;amp;+Ins(y_j)\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
 37                                s := &amp;lt;math&amp;gt;T^\ell(j)&amp;lt;/math&amp;gt;&lt;br /&gt;
 38                                &amp;lt;math&amp;gt;T^\ell(j)&amp;lt;/math&amp;gt; := c&lt;br /&gt;
 39                        end loop&lt;br /&gt;
 40                end loop&lt;br /&gt;
 41                -- finde minimalen score-pfad &amp;#039;&amp;#039;&amp;#039;nach&amp;#039;&amp;#039;&amp;#039; &amp;lt;math&amp;gt;(i_2,j_2)&amp;lt;/math&amp;gt;&lt;br /&gt;
 42                &amp;lt;math&amp;gt;T^r(j_2)&amp;lt;/math&amp;gt; := 0&lt;br /&gt;
 43                for j in &amp;lt;math&amp;gt;j_2-1&amp;lt;/math&amp;gt;..&amp;lt;math&amp;gt;j_1&amp;lt;/math&amp;gt; loop&lt;br /&gt;
 44                        &amp;lt;math&amp;gt;T^r(j)&amp;lt;/math&amp;gt; := &amp;lt;math&amp;gt;T^r(j+1) + Ins(y_{j+1})&amp;lt;/math&amp;gt;&lt;br /&gt;
 45                end loop&lt;br /&gt;
 46                for i in &amp;lt;math&amp;gt;i_2-1&amp;lt;/math&amp;gt;..mitte loop&lt;br /&gt;
 47                        s := &amp;lt;math&amp;gt;T^r(j_2)&amp;lt;/math&amp;gt;&lt;br /&gt;
 48                        c := &amp;lt;math&amp;gt;T^r(j_2) + Del(x_{i+1})&amp;lt;/math&amp;gt;&lt;br /&gt;
 49                        &amp;lt;math&amp;gt;T^r(j_2)&amp;lt;/math&amp;gt; := c;&lt;br /&gt;
 50                        for j in &amp;lt;math&amp;gt;j_2-1&amp;lt;/math&amp;gt;..&amp;lt;math&amp;gt;j_1&amp;lt;/math&amp;gt; loop&lt;br /&gt;
 51                                c := &amp;lt;math&amp;gt;\min\begin{cases}T^r(j)&amp;amp;+Del(x_{i+1})\\s&amp;amp;+Sub(x_{i+1},y_{j+1})\\c&amp;amp;+Ins(y_{j+1})\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
 52                                s := &amp;lt;math&amp;gt;T^r(j)&amp;lt;/math&amp;gt;&lt;br /&gt;
 53                                &amp;lt;math&amp;gt;T^r(j)&amp;lt;/math&amp;gt; := c&lt;br /&gt;
 54                        end loop&lt;br /&gt;
 55                end loop&lt;br /&gt;
 56                -- finde den Punkt aus &amp;lt;math&amp;gt;j_1&amp;lt;/math&amp;gt;..&amp;lt;math&amp;gt;j_2&amp;lt;/math&amp;gt; in dem der Minimale Pfad die&lt;br /&gt;
 57                -- mittlere Zeile schneidet:&lt;br /&gt;
 58                -- &amp;lt;math&amp;gt;cut :=_{def} \mbox{argmin}_{j_1\leq j\leq j_2}(T^\ell(j)+T^r(j))&amp;lt;/math&amp;gt;&lt;br /&gt;
 59                for j in &amp;lt;math&amp;gt;j_1&amp;lt;/math&amp;gt;..&amp;lt;math&amp;gt;j_2&amp;lt;/math&amp;gt; loop&lt;br /&gt;
 60                        if j=&amp;lt;math&amp;gt;j_1&amp;lt;/math&amp;gt; then&lt;br /&gt;
 61                                cut := &amp;lt;math&amp;gt;j_1&amp;lt;/math&amp;gt;&lt;br /&gt;
 62                        elsif &amp;lt;math&amp;gt;T^\ell(j)+T^r(j)&amp;lt;T^\ell(cut)+T^r(cut)&amp;lt;/math&amp;gt; then&lt;br /&gt;
 63                                cut := j&lt;br /&gt;
 64                        end if&lt;br /&gt;
 65                end loop&lt;br /&gt;
 66                -- Alignment entsteht durch Konkatenation von linkem und&lt;br /&gt;
 67                -- rechtem Teil-Alignment:&lt;br /&gt;
 68                return SubAlignment(&amp;lt;math&amp;gt;i_1&amp;lt;/math&amp;gt;,&amp;lt;math&amp;gt;j_1&amp;lt;/math&amp;gt;,mitte,cut)&lt;br /&gt;
 69                                &amp;lt;math&amp;gt;\star&amp;lt;/math&amp;gt; SubAlignment(mitte,cut,&amp;lt;math&amp;gt;i_2&amp;lt;/math&amp;gt;,&amp;lt;math&amp;gt;j_2&amp;lt;/math&amp;gt;)&lt;br /&gt;
 70        end SubAlignment&lt;br /&gt;
 71        m,n : integer&lt;br /&gt;
 72 begin&lt;br /&gt;
 73        m := &amp;lt;math&amp;gt;|x|&amp;lt;/math&amp;gt;; n := &amp;lt;math&amp;gt;|y|&amp;lt;/math&amp;gt;&lt;br /&gt;
 74        -- Sonderbehandlung: &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; ist der leere String und lässt keine Zerteilung zu:&lt;br /&gt;
 75        if m=0 then&lt;br /&gt;
 76                return &amp;lt;math&amp;gt;\begin{pmatrix}-\\ y_1\end{pmatrix}\star\begin{pmatrix}-\\ y_2\end{pmatrix}\star\cdots\star\begin{pmatrix}-\\y_n\end{pmatrix}&amp;lt;/math&amp;gt;&lt;br /&gt;
 77        else&lt;br /&gt;
 78                return SubAlignment(0,0,m,n)&lt;br /&gt;
 79        end if&lt;br /&gt;
 80 end HirschbergAlignment&lt;br /&gt;
&lt;br /&gt;
== Literatur ==&lt;br /&gt;
* {{Literatur&lt;br /&gt;
   |Autor=D. S. Hirschberg&lt;br /&gt;
   |Titel=A linear space algorithm for computing maximal common subsequences&lt;br /&gt;
   |Sammelwerk=Communications of the  ACM&lt;br /&gt;
   |Band=18&lt;br /&gt;
   |Nummer=6&lt;br /&gt;
   |Datum=1975&lt;br /&gt;
   |Seiten=341-343&lt;br /&gt;
   |Sprache=en&lt;br /&gt;
   |Online=https://www.ics.uci.edu/~dan/pubs/p341-hirschberg.pdf&lt;br /&gt;
   |Format=PDF&lt;br /&gt;
   |KBytes=}}&lt;br /&gt;
* {{Literatur&lt;br /&gt;
   |Autor=Chao, K.M., Hardison, R.C. and Miller, W.&lt;br /&gt;
   |Titel=Recent developments in linear-space alignment methods: a survey&lt;br /&gt;
   |Sammelwerk=Journal of Computational Biology&lt;br /&gt;
   |Nummer=4&lt;br /&gt;
   |Datum=1994&lt;br /&gt;
   |Seiten=271–291&lt;br /&gt;
   |Sprache=en&lt;br /&gt;
   |Online=https://www.csie.ntu.edu.tw/~kmchao/papers/1994_JCB.pdf&lt;br /&gt;
   |Format=PDF&lt;br /&gt;
   |KBytes=}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Algorithmus]]&lt;br /&gt;
[[Kategorie:Bioinformatik]]&lt;br /&gt;
[[Kategorie:Dynamische Programmierung]]&lt;br /&gt;
[[Kategorie:Parallelverarbeitung|Parallele Programmierung]]&lt;/div&gt;</summary>
		<author><name>imported&gt;Invisigoth67</name></author>
	</entry>
</feed>