\section{Strings} \begin{algorithm}{\textsc{Knuth-Morris-Pratt}-Algorithmus} \begin{methods} \method{kmpSearch}{sucht \code{sub} in \code{s}}{\abs{s}+\abs{sub}} \end{methods} \sourcecode{string/kmp.cpp} \end{algorithm} \begin{algorithm}{Z-Algorithmus} \begin{methods}[ll] $z_i\coloneqq$ Längstes gemeinsames Präfix von $s_0\cdots s_{n-1}$ und $s_i\cdots s_{n-1}$ & \runtime{n} \end{methods} Suchen: Z-Algorithmus auf \code{P\$S} ausführen, Positionen mit $z_i=\abs{P}$ zurückgeben \sourcecode{string/z.cpp} \end{algorithm} \begin{algorithm}{Trie} \sourcecode{string/trie.cpp} \end{algorithm} \begin{algorithm}{Longest Common Subsequence} \begin{methods} \method{lcss}{findet längste gemeinsame Sequenz}{\abs{a}\*\abs{b}} \end{methods} \sourcecode{string/longestCommonSubsequence.cpp} \end{algorithm} \begin{algorithm}{\textsc{Manacher}'s Algorithm, Longest Palindrome} \begin{methods} \method{init}{transformiert \code{string a}}{n} \method{manacher}{berechnet Länge der Palindrome}{n} \end{methods} \sourcecode{string/manacher.cpp} \end{algorithm} \begin{algorithm}{Rolling Hash} \sourcecode{string/rollingHash.cpp} \end{algorithm} \begin{algorithm}{\textsc{Aho-Corasick}-Automat} \begin{methods}[ll] sucht patterns im Text & \runtime{\abs{Text}+\sum\abs{pattern}+\abs{matches}} \end{methods} \begin{enumerate} \item mit \code{addString(pattern, idx);} Patterns hinzufügen. \item mit \code{state = go(state, idx)} in nächsten Zustand wechseln. \item mit \code{state = getExit(state)} den exit Kanten folgen bis \code{state == 0} \item dabei mit \code{aho[state].patterns} die Matches zählen \end{enumerate} \sourcecode{string/ahoCorasick.cpp} \end{algorithm} \begin{algorithm}{Suffix-Baum} \begin{methods} \method{SuffixTree}{berechnet einen Suffixbaum}{\abs{s}} \method{extend}{fügt den nächsten Buchstaben aus \code{s} ein}{1} \end{methods} \sourcecode{string/suffixTree.cpp} \end{algorithm} \begin{algorithm}{Suffix-Array} \begin{methods} \method{SuffixArray}{berechnet ein Suffix Array}{\abs{s}\*\log^2(\abs{s})} \method{lcp}{berechnet den logest common prefix}{\log(\abs{s})} \method{}{von \code{s[x]} und \code{s[y]}}{} \end{methods} \textbf{ACHTUNG:} \code{s} muss mit einem sentinel enden! \code{'\$'} oder \code{'#'} \sourcecode{string/suffixArray.cpp} \end{algorithm} \begin{algorithm}{Suffix-Automaton} \sourcecode{string/suffixAutomaton.cpp} \begin{itemize} \item \textbf{Ist \textit{w} Substring von \textit{s}?} Baue Automaten für \textit{s} und wende ihn auf \textit{w} an. Wenn alle Übergänge vorhanden sind, ist \textit{w} Substring von \textit{s}. \item \textbf{Ist \textit{w} Suffix von \textit{s}?} Wie oben. Überprüfe am Ende, ob aktueller Zustand ein Terminal ist. \item \textbf{Anzahl verschiedener Substrings.} Jeder Pfad im Automaten entspricht einem Substring. Für einen Knoten ist die Anzahl der ausgehenden Pfade gleich der Summe über die Anzahlen der Kindknoten plus 1. Der letzte Summand ist der Pfad, der in diesem Knoten endet. \item \textbf{Wie oft taucht \textit{w} in \textit{s} auf?} Sei \textit{p} der Zustand nach Abarbeitung von \textit{w}. Lösung ist Anzahl der Pfade, die in \textit{p} starten und in einem Terminal enden. Diese Zahl lässt sich wie oben rekursiv berechnen. Bei jedem Knoten darf nur dann plus 1 gerechnet werden, wenn es ein Terminal ist. \end{itemize} \end{algorithm} \begin{algorithm}{Lyndon und De-Bruijn} \begin{itemize} \item \textbf{Lyndon-Wort:} Ein Wort das lexikographisch kleiner ist als jede seiner Rotationen. \item Jedes Wort kann \emph{eindeutig} in eine nicht ansteigende Folge von Lyndon-Worten zerlegt werden. \item Für Lyndon-Worte $u, v$ mit $u