Algorithmen und Datenstrukturen

Ähnliche Dokumente
Hallo Welt für Fortgeschrittene

Zeichenketten. Hauptseminar Hallo Welt! für Fortgeschrittene. SS Mai 2006 Tobias Hager.

Sortieralgorithmen. Inhalt: InsertionSort BubbleSort QuickSort. Marco Block

Lösungsvorschläge. zu den Aufgaben im Kapitel 4

Programmierkurs Java

Wirtschaftsinformatik I

Algorithmische Bioinformatik

Proseminar "Pattern Matching"

Abschnitt: Algorithmendesign und Laufzeitanalyse

Grundlagen der Programmierung Prof. H. Mössenböck. 14. Schrittweise Verfeinerung

Einführung Datentypen Verzweigung Schleifen Funktionen Dynamische Datenstrukturen. Java Crashkurs. Kim-Manuel Klein

Sin-Funktion vgl. Cos-Funktion

Überblick. Lineares Suchen

Übungspaket 31 Entwicklung eines einfachen Kellerspeiches (Stacks)

Bioinformatik. Zeichenketten und Stringalgorithmen. Ulf Leser Wissensmanagement in der. Bioinformatik

Informatik Repetitorium SS Volker Jaedicke

Rekursion. Annabelle Klarl. Einführung in die Informatik Programmierung und Softwareentwicklung

II. Grundlagen der Programmierung. 9. Datenstrukturen. Daten zusammenfassen. In Java (Forts.): In Java:

M. Graefenhan Übungen zu C. Blatt 3. Musterlösung

C allgemein. C wurde unter und für Unix entwickelt. Vorläufer sind BCPL und B.

Klausur in Programmieren

VBA-Programmierung: Zusammenfassung

Gliederung. Tutorium zur Vorlesung. Gliederung. Gliederung. 1. Gliederung der Informatik. 1. Gliederung der Informatik. 1. Gliederung der Informatik

Algorithmen und Datenstrukturen

Einführung in die Informatik 1

Hochschule Darmstadt Informatik-Praktikum (INF 1) WS 2015/2016 Wirtschaftsingenieur Bachelor 5. Aufgabe Datenstruktur, Dateieingabe und -ausgabe

Programmierung in C. Grundlagen. Stefan Kallerhoff

Modul 122 VBA Scribt.docx

Informatik. Studiengang Chemische Technologie. Michael Roth WS 2012/2013. Hochschule Darmstadt -Fachbereich Informatik-

Teil 2 - Softwaretechnik. Modul: Programmierung B-PRG Grundlagen der Programmierung 1 Teil 2. Übersicht. Softwaretechnik

Suchen in Listen und Hashtabellen

4 Codierung nach Viginere (Lösung)

E-PRIME TUTORIUM Die Programmiersprache BASIC

Übersicht. Datenstrukturen und Algorithmen. Übersicht. Divide-and-Conquer. Vorlesung 9: Quicksort (K7)

Kapitel 2: Formale Sprachen Kontextfreie Sprachen. reguläre Grammatiken/Sprachen. kontextfreie Grammatiken/Sprachen

Einführung in die Programmierung Arrays, Zeiger, Strings. Arvid Terzibaschian

Hochschule Darmstadt Informatik-Praktikum (INF 1) WS 2014/2015 Wirtschaftsingenieur Bachelor 4. Aufgabe Datenstruktur, Dateieingabe und -ausgabe

Binäre lineare Optimierung mit K*BMDs p.1/42

Definition Suffixbaum

Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung)

Microcontroller / C-Programmierung Selbststudium Semesterwoche 1

Grundlagen der Informatik. Prof. Dr. Stefan Enderle NTA Isny

Klausur in Programmieren

Klausur in Programmieren

Test-Driven Design: Ein einfaches Beispiel

Sortieren. Eine Testmenge erstellen

Inf 12 Aufgaben

8 Diskrete Optimierung

Programmiersprachen Einführung in C. Unser erstes C-Programm. Unser erstes C-Programm. Unser erstes C-Programm. Unser erstes C-Programm

1. Übung zu "Numerik partieller Differentialgleichungen"

Tutorium Rechnerorganisation

Noch für heute: primitive Datentypen in JAVA. Primitive Datentypen. Pseudocode. Dezimal-, Binär- und Hexadezimalsystem. der logische Typ boolean

1. Grundlagen Sortieren Vertauschen Selektion Einfügen Quicksort Suchen...

Angewandte Mathematik und Programmierung

Studentische Lösung zum Übungsblatt Nr. 7

Autor: Michael Spahn Version: 1.0 1/10 Vertraulichkeit: öffentlich Status: Final Metaways Infosystems GmbH

Präfx Trie zur Stringverarbeitung. Cheng Ying Sabine Laubichler Vasker Pokhrel

Algorithmen und Datenstrukturen 2

Programmierung und Modellierung

1. Grundlegende Konzepte in Java (6 Punkte)

Propädeutikum zur Programmierung

Reihungen. Martin Wirsing. in Zusammenarbeit mit Matthias Hölzl und Nora Koch 11/03

Übersicht. Schleifen. Schleifeninvarianten. Referenztypen, Wrapperklassen und API. 9. November 2009 CoMa I WS 08/09 1/15

1 Vom Problem zum Programm

Algorithmen und Datenstrukturen Suchbaum

Kontrollstrukturen, Pseudocode und Modulo-Rechnung

1. Musterlösung. Problem 1: Average-case-Laufzeit vs. Worst-case-Laufzeit

SOI Die Schweizer Informatikolympiade

Probeklausur: Programmierung WS04/05

Einführung in die Programmiersprache C

Objektorientierte Programmierung

Algorithmen und Datenstrukturen

22. Algorithmus der Woche Partnerschaftsvermittlung Drum prüfe, wer sich ewig bindet

Der linke Teilbaum von v enthält nur Schlüssel < key(v) und der rechte Teilbaum enthält nur Schlüssel > key(v)

Zusammenfassung des Handzettels für Programmieren in C

Programmieren in C. -- ALLE Programmiersprachen sind HÄSSLICH -- Deklaration: erst der Datentyp, dann der Variablenname. Semikolon am Ende.

Algorithmen & Datenstrukturen 1. Klausur

Programmieren in C. Macros, Funktionen und modulare Programmstruktur. Prof. Dr. Nikolaus Wulff

Informatik I WS 07/08 Tutorium 24

Sortierverfahren. Sortierverfahren für eindimensionale Arrays

4 Greedy-Algorithmen (gierige Algorithmen)

Java programmieren: Konsolen-Programme

Algorithmische Kernsprache. Zuweisung, einfache und bedingte Anweisung, Blöcke, Schleifen, return, debugging.

Übung Grundlagen der Programmierung. Übung 03: Schleifen. Testplan Testergebnisse

Algorithmen und Datenstrukturen (ESE) Entwurf, Analyse und Umsetzung von Algorithmen (IEMS) WS 2014 / Vorlesung 5, Donnerstag, 20.

Verschlüsselung. Kirchstraße 18 Steinfelderstraße Birkweiler Bad Bergzabern Fabian Simon Bfit09

HEUTE. Effizienzbeispiel: bekannte Version (Übung ) Mathematik: Was ist Effizienz? vollständige Induktion

IT-Basics 2. DI Gerhard Fließ

Informatik II. PVK Part1 Severin Wischmann n.ethz.ch/~wiseveri

Z 50. Z O Z Int Z Komma Z Real Ziffer Komma Ziffer

HOCHSCHULE KONSTANZ TECHNIK, WIRTSCHAFT UND GESTALTUNG. Das Luzifer-Rätsel. Prof. Dr. Hartmut Plesske Wintersemester 2008/09. von.

2 Lösungen "Peptide de novo Sequencing"

AVL-Bäume Analyse. Theorem Ein AVL-Baum der Höhe h besitzt zwischen F h und 2 h 1 viele Knoten. Definition Wir definieren die nte Fibonaccizahl:

Suchen und Sortieren Sortieren. Heaps

ubasic Port für STM32F4 von Uwe Becker

Informatik II Greedy-Algorithmen

Dynamische Programmierung

Objective-C CheatSheet

Fakultät Angewandte Informatik Lehrprofessur für Informatik

Informatik-Sommercamp Mastermind mit dem Android SDK

Transkript:

Algorithmen und Datenstrukturen Prof. Martin Lercher Institut für Informatik Heinrich-Heine-Universität Düsseldorf Teil 4 Suchen in Texten Version vom: 15. November 2016 1 / 39

Vorlesung 8 15. November 2016 2 / 39

Suchen in Texten Häufig wird in einer Folge von Zeichen (in einem Text) eine Zeichenkette (ein Muster) gesucht (Pattern Matching). Man interessiert sich entweder für ein oder für alle Vorkommen des Musters im Text. Beispiele: 1 Suchmaschinen 2 Textverarbeitungsprogramme 3 Editoren 4 Filesuche 5 Mustersuche in DNA-Sequenzdaten 6 Plagiaterkennung 3 / 39

Suchen in Texten Textsuche Gegeben: Alphabet Σ, Text T Σ, T = a 0,..., a n 1 mit a i Σ und Muster P Σ, P = b 0,..., b m 1 mit b i Σ Aufgabe: Berechne i N 0 mit 0 i n m und i ist die Anfangsposition des Musters P im Text T, d.h., a i = b 0, a i+1 = b 1,..., a i+m 1 = b m 1, oder i = n falls das Muster P nicht im Text T enthalten ist. 4 / 39

Suchen in Texten - Einfache Suche Methode: Durchsuche den gesamten Text schrittweise von links nach rechts und vergleiche bei jeder Position von links das Muster zeichenweise mit dem Text. Vergleiche das Zeichen im Muster auf Position j mit dem Zeichen im Text auf Position i. Verschiebe das Wort bei einem Mismatch um eine Position nach rechts. Setze i auf i j + 1 und j auf 0. Erhöhe bei einem Match beide Indices um 1. Setze i auf i + 1 und j auf j + 1. Bei j = m wurde ein Vorkommen des Musters im Text gefunden. Setze i auf i m + 1 und j auf 0. 5 / 39

Suchen in Texten - Einfache Suche (1) int naive search (char T [ ], int n, char P[ ], int m) (2) { (3) if (m > 0) { (4) int i := 0; (5) int j := 0; (6) while ((i < n) and (j < m)) { (7) if (T [i] = P[j]) { (8) i + +; (9) j + +; (10) } (11) else { (12) i := i + 1 j; (12) j := 0; (13) } (14) } (15) if (j = m) { (16) return(i m); (17) } (18) } (19) return(n); (20) } 6 / 39

Suchen in Texten - Einfache Suche Beispiel Als Clowns verkleidete Gauner sind meist leicht zu. ^ (Mismatch) ^ (Mismatch)... ^ (Mismatch) ^ (Mismatch) ^ (Mismatch) ^ (Mismatch) 7 / 39

Suchen in Texten - Einfache Suche Beispiel Als Clowns verkleidete Gauner sind meist leicht zu.... ^ (fertig) 8 / 39

Suchen in Texten - Einfache Suche Analyse: Der naive Algorithmus führt im ungünstigsten Fall viele Vergleiche durch. (n m + 1) m O(n m) 9 / 39

Suchen in Texten - Knuth-Morris-Pratt Das Verfahren von Knuth-Morris-Pratt: Methode: Vergleiche das Zeichen im Muster auf Position j mit dem Zeichen im Text auf Position i. Wenn das Zeichen im Muster auf Position j nicht mit dem Zeichen im Text auf Position i übereinstimmt, dann setze j auf die größte Position l zwischen 0 und j 1 zurück, so das b 0,..., b l 1 = a i l,..., a i 1. Speichere die Positionen im next-array. Donald Erwin Knuth Autor von The Art of Computer programming Entwickler von TEX( L A TEX) 10 / 39

Suchen in Texten - Knuth-Morris-Pratt Beispiel Beispiel: i i i T...011011......011011......011011... P 011010 011010 011010 j j j Sei next[j] die von rechts her nächste Stelle im Muster, die man mit der i-ten Position im Text vergleichen muss, falls T [i] und P[j] verschieden sind. Beispiel Das Array next[] wird für das Muster in einer Vorphase vorausberechnet. P = 0 1 0 1 0 1 1 0 0 j = 0 1 2 3 4 5 6 7 8 next[j] = -1 0 0 1 2 3 4 0 1 11 / 39

Suchen in Texten - Knuth-Morris-Pratt Berechnung des next-arrays (1) void init next array (int next[ ], char P[ ], int m) (2) { (3) if (m > 0) { (4) int i := 0; (5) int j := 1; (6) next[0] := 1; (7) while (i < m 1) { (8) if ((j = 1) or (P[i] = P[j])) { (9) i + +; (10) j + +; (11) next[i] := j; } (12) } (13) else { (14) j := next[j]; (15) } (16) } (17) } (18) } 12 / 39

Suchen in Texten - Knuth-Morris-Pratt Textsuche mit dem berechneten next-array (1) int kmp search (char T [ ], int n, char P[ ], int m, int next[ ]) (2) { (3) if (m > 0) { (4) int i := 0; (5) int j := 0; (6) while ((i < n) and (j < m)) { (7) if ((j = 1) or (T [i] = P[j])) { (8) i + +; (9) j + +; (10) } (11) else { (12) j := next[j]; (13) } (14) } (15) if (j = m) { (16) return(i m); (17) } (18) } (19) return(n); (20) } 13 / 39

Suchen in Texten - Knuth-Morris-Pratt Analyse: Variable j kann nur so oft verkleinert werden, wie sie zuvor erhöht wurde. Variable j wird immer zusammen mit Variable i erhöht. Also wird j nur so oft verkleinert, wie i erhöht wird. Ist das next-array bekannt, so hat das Verfahren eine lineare Laufzeit O(n). Da das next-array in O(m) Schritten aufgebaut werden kann, benötigt der gesamte Algorithmus O(n + m) Schritte. 14 / 39

Das Verfahren von Boyer-Moore: Methode: Beim Verfahren von Boyer und Moore werden die Zeichen im Muster von rechts nach links mit den Zeichen im Text verglichen. Wenn es beim Vergleich der Zeichen im Text mit den Zeichen im Muster zu einem Mismatch kommt, dann verschiebe das Muster so weit wie möglich nach rechts, jedoch maximal um die Musterlänge. So weit wie möglich = setze j auf die Position des letzten Vorkommens von T [i] im Muster P. i := Position des ersten Mismatches (von rechts gesehen) im Text j := zugehörige Position im Muster (Achtung: j läuft beim Vergleich rückwärts: m 1,..., 0) 15 / 39

Beispiel Als Clowns verkleidete Gauner sind meist leicht zu. ^ (Mismatch) ^ (Mismatch) ^ (Mismatch)... ^ (Mismatch) ^ (fertig) 16 / 39

Das vereinfachte Verfahren (Heuristik) nach Boyer und Moore: Eine Verschiebung des Musters um 1 entspricht einer Erhöhung von i um (m 1 j) + 1 also um m j. Eine Verschiebung des Musters um k entspricht einer Erhöhung von i um (m 1 j) + k. Der sogenannte delta-1-wert (bad character shift) beschreibt für jedes Zeichen c im Text das erste Vorkommen des Zeiches im Muster (von rechts gezählt). Kommt c im Muster nicht vor, so ist delta-1(c) = m. 17 / 39

Beispiel Alphabet: Σ = {a, b, c, d} P = a b c a b a delta-1(a) = 0 delta-1(b) = 1 delta-1(c) = 3 delta-1(d) = 6 18 / 39

(1) int bm suche (char T [], int n, char P[], int m) (2) { (3) int i := m 1; (4) int j := m 1; (5) while ((j 0) and (i n 1)) { (6) if (T [i] = P[j]) { (7) i ; (8) j ; (9) } (10) else { (11) i := i + Musterverschiebung ; // Muss noch definiert werden! (12) j := m 1; // Neuanfang am Ende des Musters (13) } (14) } (15) if (j < 0) { (16) return (i + 1); // gefunden! (17) } (18) else (19) return (n); // nicht gefunden. (20) } (21) } 19 / 39

In dem vereinfachten Verfahren von Boyer und Moore wird immer dann, wenn es zu einem Mismatch kommt, i auf i + max{(m 1 j) + 1, delta-1(t [i])} und j auf m 1 gesetzt. Bemerkungen: Kommt es zu einem Mismatch zwischen T [i] und P[j], dann wird das Muster so weit nach rechts geschoben, bis das Zeichen T [i] im Text über dem rechtesten Vorkommen von T [i] im Muster steht. Kommt das Zeichen T [i] im Muster gar nicht vor, dann wird das Muster so weit nach rechts geschoben, bis das Zeichen T [i] im Text vor dem ersten Zeichen im Muster steht. Das Muster wird jedoch mindestens um eine Position nach rechts geschoben (i := i + m j). 20 / 39

Obwohl obiges Verfahren eine worst-case-laufzeit von O(n m) hat (T = 00 0, P = 100 0), hat es sich in der Praxis ausgezeichnet bewährt. Für genügend kurze Muster und hinreichend große Alphabete werden im Mittel O(n/m) viele Schritte durchgeführt. Das Muster wird dann also nahezu immer um seine Gesamtlänge nach rechts verschoben. 21 / 39

Kleine Modifikation Der delta-1-wert für das letzte Zeichen P[m 1] im Muster P kann auch auf das zweite Vorkommen des Zeichens im Muster (von rechts gezählt) gesetzt werden, da ein delta-1-wert von 0 eine Musterverschiebung von 0 entspricht. Beispiel mit Alphabet Σ = {a, b, c, d}: P = a b c a b a delta -1(a) = 2 delta -1(b) = 1 delta -1(c) = 3 delta -1(d) = 6 Hier wird das Muster so weit nach rechts geschoben, dass das zweite Vorkommen von rechts des letzten Zeichens im Muster unter der Position i + (m 1 j) im Text steht. 22 / 39

Verbesserung des einfachen Verfahrens von Boyer und Moore Die Sub-Muster im Muster können ähnlich wie bei dem Verfahren von Knuth Morris und Pratt mit berücksichtigt werden. Der sogenannte delta-2-wert beschreibt, um welchen Wert i maximal erhöht werden kann, wenn an einer Position j im Muster ein Mismatch eintritt. Genutzt wird die Information, dass auf den Positionen i + 1,..., i + (m 1 j) im Text die gleichen Zeichen stehen, wie im Muster auf den Positionen j,..., m 1. Wird zusätzlich noch die Information genutzt, dass auf Position i im Text ein anderes Zeichen steht als auf Position j im Muster, dann erhalten wir den verbesserten delta-2-wert. 23 / 39

Beispiel P = 1 0 0 1 0 1 0 1 0 j = 0 1 2 3 4 5 6 7 8 delta-2(j) = 15 14 13 7 6 5 4 3 1 i T...x... j j = 8 i i := i + 1 T...x... j j := m-1 24 / 39

Beispiel i T...x0... j j = 7 i i := i + 3 T...x0... j j := m-1 i T...x10... j j = 6 i i := i + 4 T...x10... j j := m-1 25 / 39

Beispiel i T...x010... j j = 5 i i := i + 5 T...x010... j j := m-1 i T...x1010... j j = 4 i i := i + 6 T...x1010... j j := m-1 26 / 39

Beispiel i T...x01010... j j = 3 i i := i + 7 T...x01010... j j := m-1 i T...x101010... j j = 2 i i := i + 13 T...x101010... j j := m-1 27 / 39

Beispiel i T...x0101010... j j = 1 i i := i + 14 T...x0101010... j j := m-1 i T...x00101010... j j = 0 i i := i + 15 T...x00101010... j j := m-1 28 / 39

In dem erweiterten Verfahren von Boyer und Moore wird immer dann, wenn es zu einem Mismatch auf Position j im Muster kommt, i auf und j auf gesetzt. Bemerkungen: i + max{delta -1(T [i]), delta-2[j]} m 1 Diese Verbesserung beseitigt zwar die worst-case Instanzen bei der Textsuche (wie bei Knuth-Morris-Pratt, hier ohne Beweis), bringt aber in der Praxis eigentlich nichts. Deshalb wird in der Regel mit der vereinfachten Version gearbeitet. Da der delta-2-wert mindestens m j ist, kann m j (Musterverschiebung um 1) aus der Maximumbildung herausgenommen werden. 29 / 39

Beispiel Beispiel für den verbesserten delta-2-wert. P = 1 0 0 1 0 1 0 1 0 j = 0 1 2 3 4 5 6 7 8 delta-2(j) = 15 14 13 7 11 7 9 7 1 i T...x... x nicht 0 j j = 8 i i := i + 1 T...x... j j := m-1 30 / 39

Beispiel i T...x0... x nicht 1 j j = 7 i i := i + 7 T...x0... j j := m-1 i T...x10... x nicht 0 j j = 6 i i := i + 9 T...x10... j j := m-1 31 / 39

Beispiel i T...x010... x nicht 1 j j = 5 i i := i + 7 T...x010... j j := m-1 i T...x1010... x nicht 0 j j = 4 i i := i + 11 T...x1010... j j := m-1 32 / 39

Beispiel i T...x01010... x nicht 1 j j = 3 i i := i + 7 T...x01010... j j := m-1 i T...x101010... x nicht 0 j j = 2 i i := i + 13 T...x101010... j j := m-1 33 / 39

Beispiel i T...x0101010... x nicht 0 j j = 1 i i := i + 14 T...x0101010... j j := m-1 i T...x00101010... x nicht 1 j j = 0 i i := i + 15 T...x00101010... j j := m-1 34 / 39

(1) int bm suche (char T [ ], int n, char P[ ], int m) (2) { (3) int i := m 1; (4) int j := m 1; (5) while ((j 0) and (i n 1)) { (6) if (T [i] = P[j]) { (7) i ; (8) j ; (9) } (10) else { (11) i := i + max{delta -1(T [i]), delta-2[j]}; (12) j := m 1; (13) }; (14) } (15) if (j < 0) { (16) return (i + 1); (17) } (18) else (19) return (n); (20) } (21) } 35 / 39

-Horspool Das Verfahren nach Boyer-Moore vereinigt die Vorteile der Match-Heuristik von Knuth-Morris-Pratt und der Occurrence-Heuristik. Es ist damit eines der theoretisch wie praktisch schnellsten Verfahren. Allerdings ist die Match-Heuristik umständlich zu implementieren. Eine vereinfachte Variante wurde von Horspool vorgeschlagen. Dieses Verfahren implementiert eine Modifikation der Occurrence-Heuristik und ist in der Praxis äusserst schnell (obwohl die worst-case Laufzeit in Θ(m n) liegt). 36 / 39

-Horspool Horspools Verfahren verschiebt immer entsprechend der letzten Position im Text, nicht entsprechend der Position die einen Mismatch ergab. Dadurch wird das Muster immer nach rechts verschoben, ohne dass wir eine Fallunterscheidung machen müssen. Wir müssen also für jeden Buchstaben des Alphabets Σ wissen, wo er im Muster am weitesten rechts (ausser ganz am Ende) vorkommt: shift[w] = { m 1 max{i < m 1 P[i] = w} falls w in P[0... m 2] m sonst 37 / 39

-Horspool (1) int bmh suche (char T [ ], int n, char P[ ], int m) (2) { (3) // Berechnung der shift-tabelle (4) for (k = 0; k < Σ ; k + +) (5) shift[k] := m ; (6) for (k = 0; k < m 1; k + +) (7) shift[p[k]] := m 1 k ; (8) // Suche (9) i := 0 ; (10) while (i + m n) { (11) j := m 1 ; (12) while (T [i + j] = P[j]) { (13) j := j ; (14) if (j < 0) (15) return(i) ; // gefunden! (16) } (17) i := i + shift[t [i + m 1]] ; // shift entspr. dem letzten Buchstaben (18) } (19) return(-1) ; // nicht gefunden. (20) } 38 / 39

-Horspool Beispiel Suche Date in Der Detektiv hatte ein Date mit der Mutter aller Clowns. 39 / 39