Handle some confilicts in chapter 1 and 2
This commit is contained in:
commit
57e13ada8b
75
book.tex
75
book.tex
|
@ -1,6 +1,6 @@
|
|||
\documentclass[twoside,12pt,a4paper,english]{book}
|
||||
|
||||
%\includeonly{luku01,kirj}
|
||||
%\includeonly{chapter01,list}
|
||||
|
||||
\usepackage[english]{babel}
|
||||
\usepackage[utf8]{inputenc}
|
||||
|
@ -27,6 +27,8 @@
|
|||
|
||||
\usepackage{titlesec}
|
||||
|
||||
\usepackage{skak}
|
||||
|
||||
\usetikzlibrary{patterns,snakes}
|
||||
\pagestyle{plain}
|
||||
|
||||
|
@ -48,6 +50,7 @@
|
|||
\author{\Large Antti Laaksonen}
|
||||
|
||||
\makeindex
|
||||
\usepackage[totoc]{idxlayout}
|
||||
|
||||
\titleformat{\subsubsection}
|
||||
{\normalfont\large\bfseries\sffamily}{\thesubsection}{1em}{}
|
||||
|
@ -64,7 +67,7 @@
|
|||
\setcounter{tocdepth}{1}
|
||||
\tableofcontents
|
||||
|
||||
\include{johdanto}
|
||||
\include{preface}
|
||||
|
||||
\mainmatter
|
||||
\pagenumbering{arabic}
|
||||
|
@ -73,41 +76,45 @@
|
|||
\newcommand{\key}[1] {\textbf{#1}}
|
||||
|
||||
\part{Basic techniques}
|
||||
\include{luku01}
|
||||
\include{luku02}
|
||||
\include{luku03}
|
||||
\include{luku04}
|
||||
\include{luku05}
|
||||
\include{luku06}
|
||||
\include{luku07}
|
||||
\include{luku08}
|
||||
\include{luku09}
|
||||
\include{luku10}
|
||||
\include{chapter01}
|
||||
\include{chapter02}
|
||||
\include{chapter03}
|
||||
\include{chapter04}
|
||||
\include{chapter05}
|
||||
\include{chapter06}
|
||||
\include{chapter07}
|
||||
\include{chapter08}
|
||||
\include{chapter09}
|
||||
\include{chapter10}
|
||||
\part{Graph algorithms}
|
||||
\include{luku11}
|
||||
\include{luku12}
|
||||
\include{luku13}
|
||||
\include{luku14}
|
||||
\include{luku15}
|
||||
\include{luku16}
|
||||
\include{luku17}
|
||||
\include{luku18}
|
||||
\include{luku19}
|
||||
\include{luku20}
|
||||
\include{chapter11}
|
||||
\include{chapter12}
|
||||
\include{chapter13}
|
||||
\include{chapter14}
|
||||
\include{chapter15}
|
||||
\include{chapter16}
|
||||
\include{chapter17}
|
||||
\include{chapter18}
|
||||
\include{chapter19}
|
||||
\include{chapter20}
|
||||
\part{Advanced topics}
|
||||
\include{luku21}
|
||||
\include{luku22}
|
||||
\include{luku23}
|
||||
\include{luku24}
|
||||
\include{luku25}
|
||||
\include{luku26}
|
||||
\include{luku27}
|
||||
\include{luku28}
|
||||
\include{luku29}
|
||||
\include{luku30}
|
||||
\include{kirj}
|
||||
\include{chapter21}
|
||||
\include{chapter22}
|
||||
\include{chapter23}
|
||||
\include{chapter24}
|
||||
\include{chapter25}
|
||||
\include{chapter26}
|
||||
\include{chapter27}
|
||||
\include{chapter28}
|
||||
\include{chapter29}
|
||||
\include{chapter30}
|
||||
|
||||
\cleardoublepage
|
||||
\phantomsection
|
||||
\addcontentsline{toc}{chapter}{Bibliography}
|
||||
\include{list}
|
||||
|
||||
\cleardoublepage
|
||||
\printindex
|
||||
|
||||
\end{document}la
|
||||
\end{document}
|
|
@ -117,10 +117,10 @@ but now it suffices to write \texttt{cout}.
|
|||
The code can be compiled using the following command:
|
||||
|
||||
\begin{lstlisting}
|
||||
g++ -std=c++11 -O2 -Wall code.cpp -o code
|
||||
g++ -std=c++11 -O2 -Wall code.cpp -o bin
|
||||
\end{lstlisting}
|
||||
|
||||
This command produces a binary file \texttt{code}
|
||||
This command produces a binary file \texttt{bin}
|
||||
from the source code \texttt{code.cpp}.
|
||||
The compiler follows the C++11 standard
|
||||
(\texttt{-std=c++11}),
|
||||
|
@ -286,7 +286,7 @@ Still, it is good to know that
|
|||
the \texttt{g++} compiler also provides
|
||||
a 128-bit type \texttt{\_\_int128\_t}
|
||||
with a value range of
|
||||
$-2^{127} \ldots 2^{127}-1$ or $-10^{38} \ldots 10^{38}$.
|
||||
$-2^{127} \ldots 2^{127}-1$ or about $-10^{38} \ldots 10^{38}$.
|
||||
However, this type is not available in all contest systems.
|
||||
|
||||
\subsubsection{Modular arithmetic}
|
||||
|
@ -624,7 +624,7 @@ For example, in the above set
|
|||
New sets can be constructed using set operations:
|
||||
\begin{itemize}
|
||||
\item The \key{intersection} $A \cap B$ consists of elements
|
||||
that are both in $A$ and $B$.
|
||||
that are in both $A$ and $B$.
|
||||
For example, if $A=\{1,2,5\}$ and $B=\{2,4\}$,
|
||||
then $A \cap B = \{2\}$.
|
||||
\item The \key{union} $A \cup B$ consists of elements
|
||||
|
@ -778,7 +778,9 @@ n! & = & n \cdot (n-1)! \\
|
|||
|
||||
\index{Fibonacci number}
|
||||
|
||||
The \key{Fibonacci numbers} arise in many situations.
|
||||
The \key{Fibonacci numbers}
|
||||
%\footnote{Fibonacci (c. 1175--1250) was an Italian mathematician.}
|
||||
arise in many situations.
|
||||
They can be defined recursively as follows:
|
||||
\[
|
||||
\begin{array}{lcl}
|
||||
|
@ -790,7 +792,8 @@ f(n) & = & f(n-1)+f(n-2) \\
|
|||
The first Fibonacci numbers are
|
||||
\[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, \ldots\]
|
||||
There is also a closed-form formula
|
||||
for calculating Fibonacci numbers:
|
||||
for calculating Fibonacci numbers\footnote{This formula is sometimes called
|
||||
\index{Binet's formula} \key{Binet's formula}.}:
|
||||
\[f(n)=\frac{(1 + \sqrt{5})^n - (1-\sqrt{5})^n}{2^n \sqrt{5}}.\]
|
||||
|
||||
\subsubsection{Logarithms}
|
||||
|
@ -887,12 +890,13 @@ The International Collegiate Programming Contest (ICPC)
|
|||
is an annual programming contest for university students.
|
||||
Each team in the contest consists of three students,
|
||||
and unlike in the IOI, the students work together;
|
||||
there is even only one computer available for each team.
|
||||
there is only one computer available for each team.
|
||||
|
||||
The ICPC consists of several stages, and finally the
|
||||
best teams are invited to the World Finals.
|
||||
While there are tens of thousands of participants
|
||||
in the contest, there are only 128 final slots available,
|
||||
in the contest, there are only a small number\footnote{The exact number of final
|
||||
slots varies from year to year; in 2016, there were 128 final slots.} of final slots available,
|
||||
so even advancing to the finals
|
||||
is a great achievement in some regions.
|
||||
|
||||
|
@ -924,7 +928,7 @@ Google Code Jam and Yandex.Algorithm.
|
|||
Of course, companies also use those contests for recruiting:
|
||||
performing well in a contest is a good way to prove one's skills.
|
||||
|
||||
\section{Books}
|
||||
\section{Resources}
|
||||
|
||||
\subsubsection{Competitive programming books}
|
||||
|
||||
|
@ -933,12 +937,11 @@ concentrate on competitive programming and algorithmic problem solving:
|
|||
|
||||
\begin{itemize}
|
||||
\item S. Halim and F. Halim:
|
||||
\emph{Competitive Programming 3: The New Lower Bound of Programming Contests}, 2013
|
||||
\emph{Competitive Programming 3: The New Lower Bound of Programming Contests} \cite{hal13}
|
||||
\item S. S. Skiena and M. A. Revilla:
|
||||
\emph{Programming Challenges: The Programming Contest Training Manual},
|
||||
Springer, 2003
|
||||
\item \emph{Looking for a Challenge? The Ultimate Problem Set from
|
||||
the University of Warsaw Programming Competitions}, 2012
|
||||
\emph{Programming Challenges: The Programming Contest Training Manual} \cite{ski03}
|
||||
\item K. Diks et al.: \emph{Looking for a Challenge? The Ultimate Problem Set from
|
||||
the University of Warsaw Programming Competitions} \cite{dik12}
|
||||
\end{itemize}
|
||||
|
||||
The first two books are intended for beginners,
|
||||
|
@ -952,9 +955,9 @@ Some good books are:
|
|||
|
||||
\begin{itemize}
|
||||
\item T. H. Cormen, C. E. Leiserson, R. L. Rivest and C. Stein:
|
||||
\emph{Introduction to Algorithms}, MIT Press, 2009 (3rd edition)
|
||||
\emph{Introduction to Algorithms} \cite{cor09}
|
||||
\item J. Kleinberg and É. Tardos:
|
||||
\emph{Algorithm Design}, Pearson, 2005
|
||||
\emph{Algorithm Design} \cite{kle05}
|
||||
\item S. S. Skiena:
|
||||
\emph{The Algorithm Design Manual}, Springer, 2008 (2nd edition)
|
||||
\emph{The Algorithm Design Manual} \cite{ski08}
|
||||
\end{itemize}
|
||||
|
|
|
@ -281,7 +281,11 @@ Still, there are many important problems for which
|
|||
no polynomial algorithm is known, i.e.,
|
||||
nobody knows how to solve them efficiently.
|
||||
\key{NP-hard} problems are an important set
|
||||
of problems, for which no polynomial algorithm is known \cite{gar79}.
|
||||
of problems, for which no polynomial algorithm
|
||||
is known\footnote{A classic book on the topic is
|
||||
M. R. Garey's and D. S. Johnson's
|
||||
\emph{Computers and Intractability: A Guide to the Theory
|
||||
of NP-Completeness} \cite{gar79}.}.
|
||||
|
||||
\section{Estimating efficiency}
|
||||
|
||||
|
@ -309,15 +313,14 @@ assuming a time limit of one second.
|
|||
|
||||
\begin{center}
|
||||
\begin{tabular}{ll}
|
||||
input size ($n$) & required time complexity \\
|
||||
typical input size & required time complexity \\
|
||||
\hline
|
||||
$n \le 10^{18}$ & $O(1)$ or $O(\log n)$ \\
|
||||
$n \le 10^{12}$ & $O(\sqrt n)$ \\
|
||||
$n \le 10^6$ & $O(n)$ or $O(n \log n)$ \\
|
||||
$n \le 5000$ & $O(n^2)$ \\
|
||||
$n \le 500$ & $O(n^3)$ \\
|
||||
$n \le 25$ & $O(2^n)$ \\
|
||||
$n \le 10$ & $O(n!)$ \\
|
||||
$n \le 20$ & $O(2^n)$ \\
|
||||
$n \le 500$ & $O(n^3)$ \\
|
||||
$n \le 5000$ & $O(n^2)$ \\
|
||||
$n \le 10^6$ & $O(n \log n)$ or $O(n)$ \\
|
||||
$n$ is large & $O(1)$ or $O(\log n)$ \\
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
|
@ -353,8 +356,8 @@ time and even in $O(n)$ time.
|
|||
|
||||
Given an array of $n$ integers $x_1,x_2,\ldots,x_n$,
|
||||
our task is to find the
|
||||
\key{maximum subarray sum}\footnote{Bentley's
|
||||
book \emph{Programming Pearls} \cite{ben86} made this problem popular.}, i.e.,
|
||||
\key{maximum subarray sum}\footnote{J. Bentley's
|
||||
book \emph{Programming Pearls} \cite{ben86} made the problem popular.}, i.e.,
|
||||
the largest possible sum of numbers
|
||||
in a contiguous region in the array.
|
||||
The problem is interesting when there may be
|
||||
|
@ -444,8 +447,8 @@ and the sum of the numbers is calculated to the variable $s$.
|
|||
The variable $p$ contains the maximum sum found during the search.
|
||||
|
||||
The time complexity of the algorithm is $O(n^3)$,
|
||||
because it consists of three nested loops and
|
||||
each loop contains $O(n)$ steps.
|
||||
because it consists of three nested loops
|
||||
that go through the input.
|
||||
|
||||
\subsubsection{Algorithm 2}
|
||||
|
||||
|
@ -471,7 +474,9 @@ After this change, the time complexity is $O(n^2)$.
|
|||
\subsubsection{Algorithm 3}
|
||||
|
||||
Surprisingly, it is possible to solve the problem
|
||||
in $O(n)$ time, which means that we can remove
|
||||
in $O(n)$ time\footnote{In \cite{ben86}, this linear-time algorithm
|
||||
is attributed to J. B. Kadene, and the algorithm is sometimes
|
||||
called \index{Kadene's algorithm} \key{Kadene's algorithm}.}, which means that we can remove
|
||||
one more loop.
|
||||
The idea is to calculate, for each array position,
|
||||
the maximum sum of a subarray that ends at that position.
|
||||
|
|
|
@ -326,7 +326,8 @@ of the algorithm is at least $O(n^2)$.
|
|||
It is possible to sort an array efficiently
|
||||
in $O(n \log n)$ time using algorithms
|
||||
that are not limited to swapping consecutive elements.
|
||||
One such algorithm is \key{mergesort}
|
||||
One such algorithm is \key{mergesort}\footnote{According to \cite{knu983},
|
||||
mergesort was invented by J. von Neumann in 1945.}
|
||||
that is based on recursion.
|
||||
|
||||
Mergesort sorts a subarray \texttt{t}$[a,b]$ as follows:
|
||||
|
@ -538,8 +539,7 @@ but use some other information.
|
|||
An example of such an algorithm is
|
||||
\key{counting sort} that sorts an array in
|
||||
$O(n)$ time assuming that every element in the array
|
||||
is an integer between $0 \ldots c$ where $c$
|
||||
is a small constant.
|
||||
is an integer between $0 \ldots c$ and $c=O(n)$.
|
||||
|
||||
The algorithm creates a \emph{bookkeeping} array
|
||||
whose indices are elements in the original array.
|
||||
|
|
|
@ -196,7 +196,7 @@ for (auto x : s) {
|
|||
}
|
||||
\end{lstlisting}
|
||||
|
||||
An important property of sets
|
||||
An important property of sets is
|
||||
that all the elements are \emph{distinct}.
|
||||
Thus, the function \texttt{count} always returns
|
||||
either 0 (the element is not in the set)
|
||||
|
@ -723,7 +723,7 @@ $5 \cdot 10^6$ & $10{,}0$ s & $2{,}3$ s & $0{,}9$ s \\
|
|||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
Algorithm 1 and 2 are equal except that
|
||||
Algorithms 1 and 2 are equal except that
|
||||
they use different set structures.
|
||||
In this problem, this choice has an important effect on
|
||||
the running time, because algorithm 2
|
||||
|
|
|
@ -436,18 +436,18 @@ the $4 \times 4$ board are numbered as follows:
|
|||
\end{tikzpicture}
|
||||
\end{center}
|
||||
|
||||
Let $q(n)$ denote the number of ways
|
||||
to place $n$ queens to te $n \times n$ chessboard.
|
||||
The above backtracking
|
||||
algorithm tells us that
|
||||
there are 92 ways to place 8
|
||||
queens to the $8 \times 8$ chessboard.
|
||||
algorithm tells us that $q(n)=92$.
|
||||
When $n$ increases, the search quickly becomes slow,
|
||||
because the number of the solutions increases
|
||||
exponentially.
|
||||
For example, calculating the ways to
|
||||
place 16 queens to the $16 \times 16$
|
||||
chessboard already takes about a minute
|
||||
on a modern computer
|
||||
(there are 14772512 solutions).
|
||||
For example, calculating $q(16)=14772512$
|
||||
using the above algorithm already takes about a minute
|
||||
on a modern computer\footnote{There is no known way to efficiently
|
||||
calculate larger values of $q(n)$. The current record is
|
||||
$q(27)=234907967154122528$, calculated in 2016 \cite{q27}.}.
|
||||
|
||||
\section{Pruning the search}
|
||||
|
||||
|
@ -716,7 +716,8 @@ check if the sum of any of the subsets is $x$.
|
|||
The running time of such a solution is $O(2^n)$,
|
||||
because there are $2^n$ subsets.
|
||||
However, using the meet in the middle technique,
|
||||
we can achieve a more efficient $O(2^{n/2})$ time solution.
|
||||
we can achieve a more efficient $O(2^{n/2})$ time solution\footnote{This
|
||||
technique was introduced in 1974 by E. Horowitz and S. Sahni \cite{hor74}.}.
|
||||
Note that $O(2^n)$ and $O(2^{n/2})$ are different
|
||||
complexities because $2^{n/2}$ equals $\sqrt{2^n}$.
|
||||
|
||||
|
|
122
chapter06.tex
122
chapter06.tex
|
@ -103,8 +103,12 @@ is 6, the greedy algorithm produces the solution
|
|||
$4+1+1$ while the optimal solution is $3+3$.
|
||||
|
||||
It is not known if the general coin problem
|
||||
can be solved using any greedy algorithm.
|
||||
can be solved using any greedy algorithm\footnote{However, it is possible
|
||||
to \emph{check} in polynomial time
|
||||
if the greedy algorithm presented in this chapter works for
|
||||
a given set of coins \cite{pea05}.}.
|
||||
However, as we will see in Chapter 7,
|
||||
in some cases,
|
||||
the general problem can be efficiently
|
||||
solved using a dynamic
|
||||
programming algorithm that always gives the
|
||||
|
@ -530,7 +534,9 @@ the string \texttt{AB} or the string \texttt{C}.
|
|||
|
||||
\subsubsection{Huffman coding}
|
||||
|
||||
\key{Huffman coding} \cite{huf52} is a greedy algorithm
|
||||
\key{Huffman coding}\footnote{D. A. Huffman discovered this method
|
||||
when solving a university course assignment
|
||||
and published the algorithm in 1952 \cite{huf52}.} is a greedy algorithm
|
||||
that constructs an optimal code for
|
||||
compressing a given string.
|
||||
The algorithm builds a binary tree
|
||||
|
@ -671,114 +677,4 @@ character & codeword \\
|
|||
\texttt{C} & 10 \\
|
||||
\texttt{D} & 111 \\
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
% \subsubsection{Miksi algoritmi toimii?}
|
||||
%
|
||||
% Huffmanin koodaus on ahne algoritmi, koska se
|
||||
% yhdistää aina kaksi solmua, joiden painot ovat
|
||||
% pienimmät.
|
||||
% Miksi on varmaa, että tämä menetelmä tuottaa
|
||||
% aina optimaalisen koodin?
|
||||
%
|
||||
% Merkitään $c(x)$ merkin $x$ esiintymiskertojen
|
||||
% määrää merkkijonossa sekä $s(x)$
|
||||
% merkkiä $x$ vastaavan koodisanan pituutta.
|
||||
% Näitä merkintöjä käyttäen merkkijonon
|
||||
% bittiesityksen pituus on
|
||||
% \[\sum_x c(x) \cdot s(x),\]
|
||||
% missä summa käy läpi kaikki merkkijonon merkit.
|
||||
% Esimerkiksi äskeisessä esimerkissä
|
||||
% bittiesityksen pituus on
|
||||
% \[5 \cdot 1 + 1 \cdot 3 + 2 \cdot 2 + 1 \cdot 3 = 15.\]
|
||||
% Hyödyllinen havainto on, että $s(x)$ on yhtä suuri kuin
|
||||
% merkkiä $x$ vastaavan solmun \emph{syvyys} puussa
|
||||
% eli matka puun huipulta solmuun.
|
||||
%
|
||||
% Perustellaan ensin, miksi optimaalista koodia vastaa
|
||||
% aina binääripuu, jossa jokaisesta solmusta lähtee
|
||||
% alaspäin joko kaksi haaraa tai ei yhtään haaraa.
|
||||
% Tehdään vastaoletus, että jostain solmusta lähtisi
|
||||
% alaspäin vain yksi haara.
|
||||
% Esimerkiksi seuraavassa puussa tällainen tilanne on solmussa $a$:
|
||||
% \begin{center}
|
||||
% \begin{tikzpicture}[scale=0.9]
|
||||
% \node[draw, circle, minimum size=20pt] (3) at (3,1) {\phantom{$a$}};
|
||||
% \node[draw, circle, minimum size=20pt] (2) at (4,0) {$b$};
|
||||
% \node[draw, circle, minimum size=20pt] (5) at (5,1) {$a$};
|
||||
% \node[draw, circle, minimum size=20pt] (6) at (4,2) {\phantom{$a$}};
|
||||
%
|
||||
% \path[draw,thick,-] (2) -- (5);
|
||||
% \path[draw,thick,-] (3) -- (6);
|
||||
% \path[draw,thick,-] (5) -- (6);
|
||||
% \end{tikzpicture}
|
||||
% \end{center}
|
||||
% Tällainen solmu $a$ on kuitenkin aina turha, koska se
|
||||
% tuo vain yhden bitin lisää polkuihin, jotka kulkevat
|
||||
% solmun kautta, eikä sen avulla voi erottaa kahta
|
||||
% koodisanaa toisistaan. Niinpä kyseisen solmun voi poistaa
|
||||
% puusta, minkä seurauksena syntyy parempi koodi,
|
||||
% eli optimaalista koodia vastaavassa puussa ei voi olla
|
||||
% solmua, josta lähtee vain yksi haara.
|
||||
%
|
||||
% Perustellaan sitten, miksi on joka vaiheessa optimaalista
|
||||
% yhdistää kaksi solmua, joiden painot ovat pienimmät.
|
||||
% Tehdään vastaoletus, että solmun $a$ paino on pienin,
|
||||
% mutta sitä ei saisi yhdistää aluksi toiseen solmuun,
|
||||
% vaan sen sijasta tulisi yhdistää solmu $b$
|
||||
% ja jokin toinen solmu:
|
||||
% \begin{center}
|
||||
% \begin{tikzpicture}[scale=0.9]
|
||||
% \node[draw, circle, minimum size=20pt] (1) at (0,0) {\phantom{$a$}};
|
||||
% \node[draw, circle, minimum size=20pt] (2) at (-2,-1) {\phantom{$a$}};
|
||||
% \node[draw, circle, minimum size=20pt] (3) at (2,-1) {$a$};
|
||||
% \node[draw, circle, minimum size=20pt] (4) at (-3,-2) {\phantom{$a$}};
|
||||
% \node[draw, circle, minimum size=20pt] (5) at (-1,-2) {\phantom{$a$}};
|
||||
% \node[draw, circle, minimum size=20pt] (8) at (-2,-3) {$b$};
|
||||
% \node[draw, circle, minimum size=20pt] (9) at (0,-3) {\phantom{$a$}};
|
||||
%
|
||||
% \path[draw,thick,-] (1) -- (2);
|
||||
% \path[draw,thick,-] (1) -- (3);
|
||||
% \path[draw,thick,-] (2) -- (4);
|
||||
% \path[draw,thick,-] (2) -- (5);
|
||||
% \path[draw,thick,-] (5) -- (8);
|
||||
% \path[draw,thick,-] (5) -- (9);
|
||||
% \end{tikzpicture}
|
||||
% \end{center}
|
||||
% Solmuille $a$ ja $b$ pätee
|
||||
% $c(a) \le c(b)$ ja $s(a) \le s(b)$.
|
||||
% Solmut aiheuttavat bittiesityksen pituuteen lisäyksen
|
||||
% \[c(a) \cdot s(a) + c(b) \cdot s(b).\]
|
||||
% Tarkastellaan sitten toista tilannetta,
|
||||
% joka on muuten samanlainen kuin ennen,
|
||||
% mutta solmut $a$ ja $b$ on vaihdettu keskenään:
|
||||
% \begin{center}
|
||||
% \begin{tikzpicture}[scale=0.9]
|
||||
% \node[draw, circle, minimum size=20pt] (1) at (0,0) {\phantom{$a$}};
|
||||
% \node[draw, circle, minimum size=20pt] (2) at (-2,-1) {\phantom{$a$}};
|
||||
% \node[draw, circle, minimum size=20pt] (3) at (2,-1) {$b$};
|
||||
% \node[draw, circle, minimum size=20pt] (4) at (-3,-2) {\phantom{$a$}};
|
||||
% \node[draw, circle, minimum size=20pt] (5) at (-1,-2) {\phantom{$a$}};
|
||||
% \node[draw, circle, minimum size=20pt] (8) at (-2,-3) {$a$};
|
||||
% \node[draw, circle, minimum size=20pt] (9) at (0,-3) {\phantom{$a$}};
|
||||
%
|
||||
% \path[draw,thick,-] (1) -- (2);
|
||||
% \path[draw,thick,-] (1) -- (3);
|
||||
% \path[draw,thick,-] (2) -- (4);
|
||||
% \path[draw,thick,-] (2) -- (5);
|
||||
% \path[draw,thick,-] (5) -- (8);
|
||||
% \path[draw,thick,-] (5) -- (9);
|
||||
% \end{tikzpicture}
|
||||
% \end{center}
|
||||
% Osoittautuu, että tätä puuta vastaava koodi on
|
||||
% \emph{yhtä hyvä tai parempi} kuin alkuperäinen koodi, joten vastaoletus
|
||||
% on väärin ja Huffmanin koodaus
|
||||
% toimiikin oikein, jos se yhdistää aluksi solmun $a$
|
||||
% jonkin solmun kanssa.
|
||||
% Tämän perustelee seuraava epäyhtälöketju:
|
||||
% \[\begin{array}{rcl}
|
||||
% c(b) & \ge & c(a) \\
|
||||
% c(b)\cdot(s(b)-s(a)) & \ge & c(a)\cdot (s(b)-s(a)) \\
|
||||
% c(b)\cdot s(b)-c(b)\cdot s(a) & \ge & c(a)\cdot s(b)-c(a)\cdot s(a) \\
|
||||
% c(a)\cdot s(a)+c(b)\cdot s(b) & \ge & c(a)\cdot s(b)+c(b)\cdot s(a) \\
|
||||
% \end{array}\]
|
||||
\end{center}
|
|
@ -708,7 +708,8 @@ depends on the values of the objects.
|
|||
\index{edit distance}
|
||||
\index{Levenshtein distance}
|
||||
|
||||
The \key{edit distance} or \key{Levenshtein distance}
|
||||
The \key{edit distance} or \key{Levenshtein distance}\footnote{The distance
|
||||
is named after V. I. Levenshtein who discussed it in connection with binary codes \cite{lev66}.}
|
||||
is the minimum number of editing operations
|
||||
needed to transform a string
|
||||
into another string.
|
||||
|
@ -983,9 +984,10 @@ $2^m$ distinct rows and the time complexity is
|
|||
$O(n 2^{2m})$.
|
||||
|
||||
As a final note, there is also a surprising direct formula
|
||||
for calculating the number of tilings\footnote{Surprisingly,
|
||||
this formula was discovered independently
|
||||
by \cite{kas61} and \cite{tem61} in 1961.}:
|
||||
for calculating the number of tilings:
|
||||
% \footnote{Surprisingly,
|
||||
% this formula was discovered independently
|
||||
% by \cite{kas61} and \cite{tem61} in 1961.}:
|
||||
\[ \prod_{a=1}^{\lceil n/2 \rceil} \prod_{b=1}^{\lceil m/2 \rceil} 4 \cdot (\cos^2 \frac{\pi a}{n + 1} + \cos^2 \frac{\pi b}{m+1})\]
|
||||
This formula is very efficient, because it calculates
|
||||
the number of tilings in $O(nm)$ time,
|
||||
|
|
|
@ -440,7 +440,8 @@ we can conclude that $\textrm{rmq}(2,7)=1$.
|
|||
\index{binary indexed tree}
|
||||
\index{Fenwick tree}
|
||||
|
||||
A \key{binary indexed tree} or \key{Fenwick tree} \cite{fen94}
|
||||
A \key{binary indexed tree} or \key{Fenwick tree}\footnote{The
|
||||
binary indexed tree structure was presented by P. M. Fenwick in 1994 \cite{fen94}.}
|
||||
can be seen as a dynamic version of a prefix sum array.
|
||||
This data structure supports two $O(\log n)$ time operations:
|
||||
calculating the sum of elements in a range
|
||||
|
@ -738,7 +739,9 @@ takes $O(1)$ time using bit operations.
|
|||
|
||||
\index{segment tree}
|
||||
|
||||
A \key{segment tree} is a data structure
|
||||
A \key{segment tree}\footnote{The origin of this structure is unknown.
|
||||
The bottom-up-implementation in this chapter corresponds to
|
||||
the implementation in \cite{sta06}.} is a data structure
|
||||
that supports two operations:
|
||||
processing a range query and
|
||||
modifying an element in the array.
|
||||
|
|
|
@ -391,7 +391,8 @@ to change an iteration over permutations into
|
|||
an iteration over subsets, so that
|
||||
the dynamic programming state
|
||||
contains a subset of a set and possibly
|
||||
some additional information.
|
||||
some additional information\footnote{This technique was introduced in 1962
|
||||
by M. Held and R. M. Karp \cite{hel62}.}.
|
||||
|
||||
The benefit in this is that
|
||||
$n!$, the number of permutations of an $n$ element set,
|
||||
|
|
|
@ -24,7 +24,9 @@ for finding shortest paths.
|
|||
|
||||
\index{Bellman–Ford algorithm}
|
||||
|
||||
The \key{Bellman–Ford algorithm} \cite{bel58} finds the
|
||||
The \key{Bellman–Ford algorithm}\footnote{The algorithm is named after
|
||||
R. E. Bellman and L. R. Ford who published it independently
|
||||
in 1958 and 1956, respectively \cite{bel58,for56a}.} finds the
|
||||
shortest paths from a starting node to all
|
||||
other nodes in the graph.
|
||||
The algorithm can process all kinds of graphs,
|
||||
|
@ -331,7 +333,9 @@ original Bellman–Ford algorithm.
|
|||
|
||||
\index{Dijkstra's algorithm}
|
||||
|
||||
\key{Dijkstra's algorithm} \cite{dij59} finds the shortest
|
||||
\key{Dijkstra's algorithm}\footnote{E. W. Dijkstra published the algorithm in 1959 \cite{dij59};
|
||||
however, his original paper does not mention how to implement the algorithm efficiently.}
|
||||
finds the shortest
|
||||
paths from the starting node to all other nodes,
|
||||
like the Bellman–Ford algorithm.
|
||||
The benefit in Dijsktra's algorithm is that
|
||||
|
@ -594,7 +598,9 @@ at most one distance to the priority queue.
|
|||
|
||||
\index{Floyd–Warshall algorithm}
|
||||
|
||||
The \key{Floyd–Warshall algorithm} \cite{flo62}
|
||||
The \key{Floyd–Warshall algorithm}\footnote{The algorithm
|
||||
is named after R. W. Floyd and S. Warshall
|
||||
who published it independently in 1962 \cite{flo62,war62}.}
|
||||
is an alternative way to approach the problem
|
||||
of finding shortest paths.
|
||||
Unlike the other algorihms in this chapter,
|
||||
|
|
|
@ -123,7 +123,8 @@ maximum spanning trees by processing the edges in reverse order.
|
|||
|
||||
\index{Kruskal's algorithm}
|
||||
|
||||
In \key{Kruskal's algorithm} \cite{kru56}, the initial spanning tree
|
||||
In \key{Kruskal's algorithm}\footnote{The algorithm was published in 1956
|
||||
by J. B. Kruskal \cite{kru56}.}, the initial spanning tree
|
||||
only contains the nodes of the graph
|
||||
and does not contain any edges.
|
||||
Then the algorithm goes through the edges
|
||||
|
@ -409,7 +410,11 @@ belongs to more than one set.
|
|||
Two $O(\log n)$ time operations are supported:
|
||||
the \texttt{union} operation joins two sets,
|
||||
and the \texttt{find} operation finds the representative
|
||||
of the set that contains a given element.
|
||||
of the set that contains a given element\footnote{The structure presented here
|
||||
was introduced in 1971 by J. D. Hopcroft and J. D. Ullman \cite{hop71}.
|
||||
Later, in 1975, R. E. Tarjan studied a more sophisticated variant
|
||||
of the structure \cite{tar75} that is discussed in many algorithm
|
||||
textbooks nowadays.}.
|
||||
|
||||
\subsubsection{Structure}
|
||||
|
||||
|
@ -567,7 +572,10 @@ the smaller set to the larger set.
|
|||
|
||||
\index{Prim's algorithm}
|
||||
|
||||
\key{Prim's algorithm} \cite{pri57} is an alternative method
|
||||
\key{Prim's algorithm}\footnote{The algorithm is
|
||||
named after R. C. Prim who published it in 1957 \cite{pri57}.
|
||||
However, the same algorithm was discovered already in 1930
|
||||
by V. Jarník.} is an alternative method
|
||||
for finding a minimum spanning tree.
|
||||
The algorithm first adds an arbitrary node
|
||||
to the tree.
|
||||
|
|
|
@ -657,7 +657,9 @@ achieves these properties.
|
|||
|
||||
\index{Floyd's algorithm}
|
||||
|
||||
\key{Floyd's algorithm} walks forward
|
||||
\key{Floyd's algorithm}\footnote{The idea of the algorithm is mentioned in \cite{knu982}
|
||||
and attributed to R. W. Floyd; however, it is not known if Floyd was the first
|
||||
who discovered the algorithm.} walks forward
|
||||
in the graph using two pointers $a$ and $b$.
|
||||
Both pointers begin at a node $x$ that
|
||||
is the starting node of the graph.
|
||||
|
|
|
@ -368,7 +368,10 @@ performs two depth-first searches.
|
|||
\index{2SAT problem}
|
||||
|
||||
Strongly connectivity is also linked with the
|
||||
\key{2SAT problem} \cite{asp79}.
|
||||
\key{2SAT problem}\footnote{The algorithm presented here was
|
||||
introduced in \cite{asp79}.
|
||||
There is also another well-known linear-time algorithm \cite{eve75}
|
||||
that is based on backtracking.}.
|
||||
In this problem, we are given a logical formula
|
||||
\[
|
||||
(a_1 \lor b_1) \land (a_2 \lor b_2) \land \cdots \land (a_m \lor b_m),
|
||||
|
|
|
@ -266,14 +266,18 @@ is $3+4+3+1=11$.
|
|||
\end{center}
|
||||
|
||||
The idea is to construct a tree traversal array that contains
|
||||
three values for each node: (1) the identifier of the node,
|
||||
(2) the size of the subtree, and (3) the value of the node.
|
||||
three values for each node: the identifier of the node,
|
||||
the size of the subtree, and the value of the node.
|
||||
For example, the array for the above tree is as follows:
|
||||
|
||||
\begin{center}
|
||||
\begin{tikzpicture}[scale=0.7]
|
||||
\draw (0,1) grid (9,-2);
|
||||
|
||||
\node[left] at (-1,0.5) {node id};
|
||||
\node[left] at (-1,-0.5) {subtree size};
|
||||
\node[left] at (-1,-1.5) {node value};
|
||||
|
||||
\node at (0.5,0.5) {$1$};
|
||||
\node at (1.5,0.5) {$2$};
|
||||
\node at (2.5,0.5) {$6$};
|
||||
|
@ -330,6 +334,10 @@ can be found as follows:
|
|||
\fill[color=lightgray] (4,-1) rectangle (8,-2);
|
||||
\draw (0,1) grid (9,-2);
|
||||
|
||||
\node[left] at (-1,0.5) {node id};
|
||||
\node[left] at (-1,-0.5) {subtree size};
|
||||
\node[left] at (-1,-1.5) {node value};
|
||||
|
||||
\node at (0.5,0.5) {$1$};
|
||||
\node at (1.5,0.5) {$2$};
|
||||
\node at (2.5,0.5) {$6$};
|
||||
|
@ -438,6 +446,10 @@ For example, the following array corresponds to the above tree:
|
|||
\begin{tikzpicture}[scale=0.7]
|
||||
\draw (0,1) grid (9,-2);
|
||||
|
||||
\node[left] at (-1,0.5) {node id};
|
||||
\node[left] at (-1,-0.5) {subtree size};
|
||||
\node[left] at (-1,-1.5) {path sum};
|
||||
|
||||
\node at (0.5,0.5) {$1$};
|
||||
\node at (1.5,0.5) {$2$};
|
||||
\node at (2.5,0.5) {$6$};
|
||||
|
@ -491,6 +503,10 @@ the array changes as follows:
|
|||
\fill[color=lightgray] (4,-1) rectangle (8,-2);
|
||||
\draw (0,1) grid (9,-2);
|
||||
|
||||
\node[left] at (-1,0.5) {node id};
|
||||
\node[left] at (-1,-0.5) {subtree size};
|
||||
\node[left] at (-1,-1.5) {path sum};
|
||||
|
||||
\node at (0.5,0.5) {$1$};
|
||||
\node at (1.5,0.5) {$2$};
|
||||
\node at (2.5,0.5) {$6$};
|
||||
|
@ -562,9 +578,9 @@ is node 2:
|
|||
\node[draw, circle] (3) at (-2,1) {$2$};
|
||||
\node[draw, circle] (4) at (0,1) {$3$};
|
||||
\node[draw, circle] (5) at (2,-1) {$7$};
|
||||
\node[draw, circle] (6) at (-3,-1) {$5$};
|
||||
\node[draw, circle, fill=lightgray] (6) at (-3,-1) {$5$};
|
||||
\node[draw, circle] (7) at (-1,-1) {$6$};
|
||||
\node[draw, circle] (8) at (-1,-3) {$8$};
|
||||
\node[draw, circle, fill=lightgray] (8) at (-1,-3) {$8$};
|
||||
\path[draw,thick,-] (1) -- (2);
|
||||
\path[draw,thick,-] (1) -- (3);
|
||||
\path[draw,thick,-] (1) -- (4);
|
||||
|
@ -572,6 +588,9 @@ is node 2:
|
|||
\path[draw,thick,-] (3) -- (6);
|
||||
\path[draw,thick,-] (3) -- (7);
|
||||
\path[draw,thick,-] (7) -- (8);
|
||||
|
||||
\path[draw=red,thick,->,line width=2pt] (6) edge [bend left] (3);
|
||||
\path[draw=red,thick,->,line width=2pt] (8) edge [bend right=40] (3);
|
||||
\end{tikzpicture}
|
||||
\end{center}
|
||||
|
||||
|
@ -583,13 +602,17 @@ finding the lowest common ancestor of two nodes.
|
|||
One way to solve the problem is to use the fact
|
||||
that we can efficiently find the $k$th
|
||||
ancestor of any node in the tree.
|
||||
Thus, we can first make sure that
|
||||
both nodes are at the same level in the tree,
|
||||
and then find the smallest value of $k$
|
||||
such that the $k$th ancestor of both nodes is the same.
|
||||
Using this, we can divide the problem of
|
||||
finding the lowest common ancestor into two parts.
|
||||
|
||||
As an example, let us find the lowest common
|
||||
ancestor of nodes $5$ and $8$:
|
||||
We use two pointers that initially point to the
|
||||
two nodes for which we should find the
|
||||
lowest common ancestor.
|
||||
First, we move one of the pointers upwards
|
||||
so that both nodes are at the same level in the tree.
|
||||
|
||||
In the example case, we move from node 8 to node 6,
|
||||
after which both nodes are at the same level:
|
||||
|
||||
\begin{center}
|
||||
\begin{tikzpicture}[scale=0.9]
|
||||
|
@ -599,8 +622,8 @@ ancestor of nodes $5$ and $8$:
|
|||
\node[draw, circle] (4) at (0,1) {$3$};
|
||||
\node[draw, circle] (5) at (2,-1) {$7$};
|
||||
\node[draw, circle,fill=lightgray] (6) at (-3,-1) {$5$};
|
||||
\node[draw, circle] (7) at (-1,-1) {$6$};
|
||||
\node[draw, circle,fill=lightgray] (8) at (-1,-3) {$8$};
|
||||
\node[draw, circle,fill=lightgray] (7) at (-1,-1) {$6$};
|
||||
\node[draw, circle] (8) at (-1,-3) {$8$};
|
||||
\path[draw,thick,-] (1) -- (2);
|
||||
\path[draw,thick,-] (1) -- (3);
|
||||
\path[draw,thick,-] (1) -- (4);
|
||||
|
@ -608,26 +631,30 @@ ancestor of nodes $5$ and $8$:
|
|||
\path[draw,thick,-] (3) -- (6);
|
||||
\path[draw,thick,-] (3) -- (7);
|
||||
\path[draw,thick,-] (7) -- (8);
|
||||
|
||||
\path[draw=red,thick,->,line width=2pt] (8) edge [bend right] (7);
|
||||
\end{tikzpicture}
|
||||
\end{center}
|
||||
|
||||
Node $5$ is at level $3$, while node $8$ is at level $4$.
|
||||
Thus, we first move one step upwards from node $8$ to node $6$.
|
||||
After this, it turns out that the parent of both nodes $5$
|
||||
and $6$ is node $2$, so we have found the lowest common ancestor.
|
||||
After this, we determine the minimum number of steps
|
||||
needed to move both pointers upwards so that
|
||||
they will point to the same node.
|
||||
This node is the lowest common ancestor of the nodes.
|
||||
|
||||
The following picture shows how we move in the tree:
|
||||
In the example case, it suffices to move both pointers
|
||||
one step upwards to node 2,
|
||||
which is the lowest common ancestor:
|
||||
|
||||
\begin{center}
|
||||
\begin{tikzpicture}[scale=0.9]
|
||||
\node[draw, circle] (1) at (0,3) {$1$};
|
||||
\node[draw, circle] (2) at (2,1) {$4$};
|
||||
\node[draw, circle] (3) at (-2,1) {$2$};
|
||||
\node[draw, circle,fill=lightgray] (3) at (-2,1) {$2$};
|
||||
\node[draw, circle] (4) at (0,1) {$3$};
|
||||
\node[draw, circle] (5) at (2,-1) {$7$};
|
||||
\node[draw, circle,fill=lightgray] (6) at (-3,-1) {$5$};
|
||||
\node[draw, circle] (6) at (-3,-1) {$5$};
|
||||
\node[draw, circle] (7) at (-1,-1) {$6$};
|
||||
\node[draw, circle,fill=lightgray] (8) at (-1,-3) {$8$};
|
||||
\node[draw, circle] (8) at (-1,-3) {$8$};
|
||||
\path[draw,thick,-] (1) -- (2);
|
||||
\path[draw,thick,-] (1) -- (3);
|
||||
\path[draw,thick,-] (1) -- (4);
|
||||
|
@ -637,20 +664,21 @@ The following picture shows how we move in the tree:
|
|||
\path[draw,thick,-] (7) -- (8);
|
||||
|
||||
\path[draw=red,thick,->,line width=2pt] (6) edge [bend left] (3);
|
||||
\path[draw=red,thick,->,line width=2pt] (8) edge [bend right] (7);
|
||||
\path[draw=red,thick,->,line width=2pt] (7) edge [bend right] (3);
|
||||
\end{tikzpicture}
|
||||
\end{center}
|
||||
|
||||
Using this method, we can find the lowest common ancestor
|
||||
of any two nodes in $O(\log n)$ time after an $O(n \log n)$ time
|
||||
preprocessing, because both steps can be
|
||||
performed in $O(\log n)$ time.
|
||||
Since both parts of the algorithm can be performed in
|
||||
$O(\log n)$ time using precomputed information,
|
||||
we can find the lowest common ancestor of any two
|
||||
nodes in $O(\log n)$ time using this technique.
|
||||
|
||||
\subsubsection{Method 2}
|
||||
|
||||
Another way to solve the problem is based on
|
||||
a tree traversal array \cite{ben00}.
|
||||
a tree traversal array\footnote{This lowest common ancestor algorithm is based on \cite{ben00}.
|
||||
This technique is sometimes called the \index{Euler tour technique}
|
||||
\key{Euler tour technique} \cite{tar84}.}.
|
||||
Once again, the idea is to traverse the nodes
|
||||
using a depth-first search:
|
||||
|
||||
|
@ -689,23 +717,26 @@ using a depth-first search:
|
|||
\end{tikzpicture}
|
||||
\end{center}
|
||||
|
||||
However, we use a bit different variant of
|
||||
the tree traversal array where
|
||||
However, we use a bit different tree
|
||||
traversal array than before:
|
||||
we add each node to the array \emph{always}
|
||||
when the depth-first search visits the node,
|
||||
when the depth-first search walks through the node,
|
||||
and not only at the first visit.
|
||||
Hence, a node that has $k$ children appears $k+1$ times
|
||||
in the array, and there are a total of $2n-1$
|
||||
in the array and there are a total of $2n-1$
|
||||
nodes in the array.
|
||||
|
||||
We store two values in the array:
|
||||
(1) the identifier of the node, and (2) the level of the
|
||||
the identifier of the node and the level of the
|
||||
node in the tree.
|
||||
The following array corresponds to the above tree:
|
||||
|
||||
\begin{center}
|
||||
\begin{tikzpicture}[scale=0.7]
|
||||
|
||||
\node[left] at (-1,1.5) {node id};
|
||||
\node[left] at (-1,0.5) {level};
|
||||
|
||||
\draw (0,1) grid (15,2);
|
||||
%\node at (-1.1,1.5) {\texttt{node}};
|
||||
\node at (0.5,1.5) {$1$};
|
||||
|
@ -770,6 +801,10 @@ can be found as follows:
|
|||
|
||||
\begin{center}
|
||||
\begin{tikzpicture}[scale=0.7]
|
||||
|
||||
\node[left] at (-1,1.5) {node id};
|
||||
\node[left] at (-1,0.5) {level};
|
||||
|
||||
\fill[color=lightgray] (2,1) rectangle (3,2);
|
||||
\fill[color=lightgray] (5,1) rectangle (6,2);
|
||||
\fill[color=lightgray] (2,0) rectangle (6,1);
|
||||
|
|
|
@ -22,7 +22,9 @@ problem and no efficient algorithm is known for solving the problem.
|
|||
|
||||
\index{Eulerian path}
|
||||
|
||||
An \key{Eulerian path} is a path
|
||||
An \key{Eulerian path}\footnote{L. Euler (1707--1783) studied such paths in 1736
|
||||
when he solved the famous Königsberg bridge problem.
|
||||
This was the birth of graph theory.} is a path
|
||||
that goes exactly once through each edge in the graph.
|
||||
For example, the graph
|
||||
\begin{center}
|
||||
|
@ -222,7 +224,8 @@ from node 2 to node 5:
|
|||
|
||||
\index{Hierholzer's algorithm}
|
||||
|
||||
\key{Hierholzer's algorithm} is an efficient
|
||||
\key{Hierholzer's algorithm}\footnote{The algorithm was published
|
||||
in 1873 after Hierholzer's death \cite{hie73}.} is an efficient
|
||||
method for constructing
|
||||
an Eulerian circuit.
|
||||
The algorithm consists of several rounds,
|
||||
|
@ -395,7 +398,9 @@ so we have successfully constructed an Eulerian circuit.
|
|||
|
||||
\index{Hamiltonian path}
|
||||
|
||||
A \key{Hamiltonian path} is a path
|
||||
A \key{Hamiltonian path}
|
||||
%\footnote{W. R. Hamilton (1805--1865) was an Irish mathematician.}
|
||||
is a path
|
||||
that visits each node in the graph exactly once.
|
||||
For example, the graph
|
||||
\begin{center}
|
||||
|
@ -481,12 +486,12 @@ Also stronger results have been achieved:
|
|||
\begin{itemize}
|
||||
\item
|
||||
\index{Dirac's theorem}
|
||||
\key{Dirac's theorem}:
|
||||
\key{Dirac's theorem}: %\cite{dir52}
|
||||
If the degree of each node is at least $n/2$,
|
||||
the graph contains a Hamiltonian path.
|
||||
\item
|
||||
\index{Ore's theorem}
|
||||
\key{Ore's theorem}:
|
||||
\key{Ore's theorem}: %\cite{ore60}
|
||||
If the sum of degrees of each non-adjacent pair of nodes
|
||||
is at least $n$,
|
||||
the graph contains a Hamiltonian path.
|
||||
|
@ -525,7 +530,9 @@ It is possible to implement this solution in $O(2^n n^2)$ time.
|
|||
|
||||
\index{De Bruijn sequence}
|
||||
|
||||
A \key{De Bruijn sequence} is a string that contains
|
||||
A \key{De Bruijn sequence}
|
||||
%\footnote{N. G. de Bruijn (1918--2012) was a Dutch mathematician.}
|
||||
is a string that contains
|
||||
every string of length $n$
|
||||
exactly once as a substring, for a fixed
|
||||
alphabet of $k$ characters.
|
||||
|
@ -546,7 +553,7 @@ and each edge adds one character to the string.
|
|||
The following graph corresponds to the above example:
|
||||
|
||||
\begin{center}
|
||||
\begin{tikzpicture}
|
||||
\begin{tikzpicture}[scale=0.8]
|
||||
\node[draw, circle] (00) at (-3,0) {00};
|
||||
\node[draw, circle] (11) at (3,0) {11};
|
||||
\node[draw, circle] (01) at (0,2) {01};
|
||||
|
@ -628,12 +635,13 @@ The search can be made more efficient by using
|
|||
\key{heuristics} that attempt to guide the knight so that
|
||||
a complete tour will be found quickly.
|
||||
|
||||
\subsubsection{Warnsdorff's rule}
|
||||
\subsubsection{Warnsdorf's rule}
|
||||
|
||||
\index{heuristic}
|
||||
\index{Warnsdorff's rule}
|
||||
\index{Warnsdorf's rule}
|
||||
|
||||
\key{Warnsdorff's rule} is a simple and effective heuristic
|
||||
\key{Warnsdorf's rule}\footnote{This heuristic was proposed
|
||||
in Warnsdorf's book \cite{war23} in 1823.} is a simple and effective heuristic
|
||||
for finding a knight's tour.
|
||||
Using the rule, it is possible to efficiently construct a tour
|
||||
even on a large board.
|
||||
|
@ -655,7 +663,7 @@ possible squares to which the knight can move:
|
|||
\node at (3.5,1.5) {$d$};
|
||||
\end{tikzpicture}
|
||||
\end{center}
|
||||
In this situation, Warnsdorff's rule moves the knight to square $a$,
|
||||
In this situation, Warnsdorf's rule moves the knight to square $a$,
|
||||
because after this choice, there is only a single possible move.
|
||||
The other choices would move the knight to squares where
|
||||
there would be three moves available.
|
||||
|
|
|
@ -24,7 +24,7 @@ z = \sqrt[3]{3}.\\
|
|||
However, nobody knows if there are any three
|
||||
\emph{integers} $x$, $y$ and $z$
|
||||
that would satisfy the equation, but this
|
||||
is an open problem in number theory.
|
||||
is an open problem in number theory \cite{bec07}.
|
||||
|
||||
In this chapter, we will focus on basic concepts
|
||||
and algorithms in number theory.
|
||||
|
@ -205,7 +205,9 @@ so the result of the function is $[2,2,2,3]$.
|
|||
|
||||
\index{sieve of Eratosthenes}
|
||||
|
||||
The \key{sieve of Eratosthenes} is a preprocessing
|
||||
The \key{sieve of Eratosthenes}
|
||||
%\footnote{Eratosthenes (c. 276 BC -- c. 194 BC) was a Greek mathematician.}
|
||||
is a preprocessing
|
||||
algorithm that builds an array using which we
|
||||
can efficiently check if a given number between $2 \ldots n$
|
||||
is prime and, if it is not, find one prime factor of the number.
|
||||
|
@ -327,7 +329,8 @@ The greatest common divisor and the least common multiple
|
|||
are connected as follows:
|
||||
\[\textrm{lcm}(a,b)=\frac{ab}{\textrm{gcd}(a,b)}\]
|
||||
|
||||
\key{Euclid's algorithm} provides an efficient way
|
||||
\key{Euclid's algorithm}\footnote{Euclid was a Greek mathematician who
|
||||
lived in about 300 BC. This is perhaps the first known algorithm in history.} provides an efficient way
|
||||
to find the greatest common divisor of two numbers.
|
||||
The algorithm is based on the following formula:
|
||||
\begin{equation*}
|
||||
|
@ -355,6 +358,7 @@ For example,
|
|||
Numbers $a$ and $b$ are \key{coprime}
|
||||
if $\textrm{gcd}(a,b)=1$.
|
||||
\key{Euler's totient function} $\varphi(n)$
|
||||
%\footnote{Euler presented this function in 1763.}
|
||||
gives the number of coprime numbers to $n$
|
||||
between $1$ and $n$.
|
||||
For example, $\varphi(12)=4$,
|
||||
|
@ -432,12 +436,16 @@ int modpow(int x, int n, int m) {
|
|||
\index{Fermat's theorem}
|
||||
\index{Euler's theorem}
|
||||
|
||||
\key{Fermat's theorem} states that
|
||||
\key{Fermat's theorem}
|
||||
%\footnote{Fermat discovered this theorem in 1640.}
|
||||
states that
|
||||
\[x^{m-1} \bmod m = 1\]
|
||||
when $m$ is prime and $x$ and $m$ are coprime.
|
||||
This also yields
|
||||
\[x^k \bmod m = x^{k \bmod (m-1)} \bmod m.\]
|
||||
More generally, \key{Euler's theorem} states that
|
||||
More generally, \key{Euler's theorem}
|
||||
%\footnote{Euler published this theorem in 1763.}
|
||||
states that
|
||||
\[x^{\varphi(m)} \bmod m = 1\]
|
||||
when $x$ and $m$ are coprime.
|
||||
Fermat's theorem follows from Euler's theorem,
|
||||
|
@ -517,7 +525,9 @@ cout << x*x << "\n"; // 2537071545
|
|||
|
||||
\index{Diophantine equation}
|
||||
|
||||
A \key{Diophantine equation} is an equation of the form
|
||||
A \key{Diophantine equation}
|
||||
%\footnote{Diophantus of Alexandria was a Greek mathematician who lived in the 3th century.}
|
||||
is an equation of the form
|
||||
\[ ax + by = c, \]
|
||||
where $a$, $b$ and $c$ are constants
|
||||
and we should find the values of $x$ and $y$.
|
||||
|
@ -637,7 +647,9 @@ are solutions.
|
|||
|
||||
\index{Lagrange's theorem}
|
||||
|
||||
\key{Lagrange's theorem} states that every positive integer
|
||||
\key{Lagrange's theorem}
|
||||
%\footnote{J.-L. Lagrange (1736--1813) was an Italian mathematician.}
|
||||
states that every positive integer
|
||||
can be represented as a sum of four squares, i.e.,
|
||||
$a^2+b^2+c^2+d^2$.
|
||||
For example, the number 123 can be represented
|
||||
|
@ -648,7 +660,9 @@ as the sum $8^2+5^2+5^2+3^2$.
|
|||
\index{Zeckendorf's theorem}
|
||||
\index{Fibonacci number}
|
||||
|
||||
\key{Zeckendorf's theorem} states that every
|
||||
\key{Zeckendorf's theorem}
|
||||
%\footnote{E. Zeckendorf published the theorem in 1972 \cite{zec72}; however, this was not a new result.}
|
||||
states that every
|
||||
positive integer has a unique representation
|
||||
as a sum of Fibonacci numbers such that
|
||||
no two numbers are equal or consecutive
|
||||
|
@ -689,7 +703,9 @@ produces the smallest Pythagorean triple
|
|||
|
||||
\index{Wilson's theorem}
|
||||
|
||||
\key{Wilson's theorem} states that a number $n$
|
||||
\key{Wilson's theorem}
|
||||
%\footnote{J. Wilson (1741--1793) was an English mathematician.}
|
||||
states that a number $n$
|
||||
is prime exactly when
|
||||
\[(n-1)! \bmod n = n-1.\]
|
||||
For example, the number 11 is prime, because
|
||||
|
|
|
@ -342,7 +342,9 @@ corresponds to the binomial coefficient formula.
|
|||
|
||||
\index{Catalan number}
|
||||
|
||||
The \key{Catalan number} $C_n$ equals the
|
||||
The \key{Catalan number}
|
||||
%\footnote{E. C. Catalan (1814--1894) was a Belgian mathematician.}
|
||||
$C_n$ equals the
|
||||
number of valid
|
||||
parenthesis expressions that consist of
|
||||
$n$ left parentheses and $n$ right parentheses.
|
||||
|
@ -678,7 +680,9 @@ elements should be changed.
|
|||
|
||||
\index{Burnside's lemma}
|
||||
|
||||
\key{Burnside's lemma} can be used to count
|
||||
\key{Burnside's lemma}
|
||||
%\footnote{Actually, Burnside did not discover this lemma; he only mentioned it in his book \cite{bur97}.}
|
||||
can be used to count
|
||||
the number of combinations so that
|
||||
only one representative is counted
|
||||
for each group of symmetric combinations.
|
||||
|
@ -764,7 +768,10 @@ with 3 colors is
|
|||
|
||||
\index{Cayley's formula}
|
||||
|
||||
\key{Cayley's formula} states that
|
||||
\key{Cayley's formula}
|
||||
% \footnote{While the formula is named after A. Cayley,
|
||||
% who studied it in 1889, it was discovered earlier by C. W. Borchardt in 1860.}
|
||||
states that
|
||||
there are $n^{n-2}$ labeled trees
|
||||
that contain $n$ nodes.
|
||||
The nodes are labeled $1,2,\ldots,n$,
|
||||
|
@ -827,7 +834,9 @@ be derived using Prüfer codes.
|
|||
|
||||
\index{Prüfer code}
|
||||
|
||||
A \key{Prüfer code} is a sequence of
|
||||
A \key{Prüfer code}
|
||||
%\footnote{In 1918, H. Prüfer proved Cayley's theorem using Prüfer codes \cite{pru18}.}
|
||||
is a sequence of
|
||||
$n-2$ numbers that describes a labeled tree.
|
||||
The code is constructed by following a process
|
||||
that removes $n-2$ leaves from the tree.
|
||||
|
|
|
@ -245,8 +245,9 @@ two $n \times n$ matrices
|
|||
in $O(n^3)$ time.
|
||||
There are also more efficient algorithms
|
||||
for matrix multiplication\footnote{The first such
|
||||
algorithm, with time complexity $O(n^{2.80735})$,
|
||||
was published in 1969 \cite{str69}, and
|
||||
algorithm was Strassen's algorithm,
|
||||
published in 1969 \cite{str69},
|
||||
whose time complexity is $O(n^{2.80735})$;
|
||||
the best current algorithm
|
||||
works in $O(n^{2.37286})$ time \cite{gal14}.},
|
||||
but they are mostly of theoretical interest
|
||||
|
@ -749,7 +750,9 @@ $2 \rightarrow 1 \rightarrow 4 \rightarrow 2 \rightarrow 5$.
|
|||
\index{Kirchhoff's theorem}
|
||||
\index{spanning tree}
|
||||
|
||||
\key{Kirchhoff's theorem} provides a way
|
||||
\key{Kirchhoff's theorem}
|
||||
%\footnote{G. R. Kirchhoff (1824--1887) was a German physicist.}
|
||||
provides a way
|
||||
to calculate the number of spanning trees
|
||||
of a graph as a determinant of a special matrix.
|
||||
For example, the graph
|
||||
|
|
|
@ -359,7 +359,10 @@ The expected value for $X$ in a geometric distribution is
|
|||
|
||||
\index{Markov chain}
|
||||
|
||||
A \key{Markov chain} is a random process
|
||||
A \key{Markov chain}
|
||||
% \footnote{A. A. Markov (1856--1922)
|
||||
% was a Russian mathematician.}
|
||||
is a random process
|
||||
that consists of states and transitions between them.
|
||||
For each state, we know the probabilities
|
||||
for moving to other states.
|
||||
|
@ -514,7 +517,11 @@ just to find one element?
|
|||
|
||||
It turns out that we can find order statistics
|
||||
using a randomized algorithm without sorting the array.
|
||||
The algorithm is a Las Vegas algorithm:
|
||||
The algorithm, called \key{quickselect}\footnote{In 1961,
|
||||
C. A. R. Hoare published two algorithms that
|
||||
are efficient on average: \index{quicksort} \index{quickselect}
|
||||
\key{quicksort} \cite{hoa61a} for sorting arrays and
|
||||
\key{quickselect} \cite{hoa61b} for finding order statistics.}, is a Las Vegas algorithm:
|
||||
its running time is usually $O(n)$
|
||||
but $O(n^2)$ in the worst case.
|
||||
|
||||
|
@ -560,7 +567,9 @@ but one could hope that verifying the
|
|||
answer would by easier than to calculate it from scratch.
|
||||
|
||||
It turns out that we can solve the problem
|
||||
using a Monte Carlo algorithm whose
|
||||
using a Monte Carlo algorithm\footnote{R. M. Freivalds published
|
||||
this algorithm in 1977 \cite{fre77}, and it is sometimes
|
||||
called \index{Freivalds' algoritm} \key{Freivalds' algorithm}.} whose
|
||||
time complexity is only $O(n^2)$.
|
||||
The idea is simple: we choose a random vector
|
||||
$X$ of $n$ elements, and calculate the matrices
|
||||
|
|
|
@ -248,7 +248,8 @@ and this is always the final state.
|
|||
It turns out that we can easily classify
|
||||
any nim state by calculating
|
||||
the \key{nim sum} $x_1 \oplus x_2 \oplus \cdots \oplus x_n$,
|
||||
where $\oplus$ is the xor operation.
|
||||
where $\oplus$ is the xor operation\footnote{The optimal strategy
|
||||
for nim was published in 1901 by C. L. Bouton \cite{bou01}.}.
|
||||
The states whose nim sum is 0 are losing states,
|
||||
and all other states are winning states.
|
||||
For example, the nim sum for
|
||||
|
@ -367,7 +368,8 @@ so the nim sum is not 0.
|
|||
|
||||
\index{Sprague–Grundy theorem}
|
||||
|
||||
The \key{Sprague–Grundy theorem} generalizes the
|
||||
The \key{Sprague–Grundy theorem}\footnote{The theorem was discovered
|
||||
independently by R. Sprague \cite{spr35} and P. M. Grundy \cite{gru39}.} generalizes the
|
||||
strategy used in nim to all games that fulfil
|
||||
the following requirements:
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ After this, it suffices to sum the areas
|
|||
of the triangles.
|
||||
The area of a triangle can be calculated,
|
||||
for example, using \key{Heron's formula}
|
||||
%\footnote{Heron of Alexandria (c. 10--70) was a Greek mathematician.}
|
||||
\[ \sqrt{s (s-a) (s-b) (s-c)},\]
|
||||
where $a$, $b$ and $c$ are the lengths
|
||||
of the triangle's sides and
|
||||
|
@ -500,7 +501,8 @@ so $b$ is outside the polygon.
|
|||
\section{Polygon area}
|
||||
|
||||
A general formula for calculating the area
|
||||
of a polygon is
|
||||
of a polygon\footnote{This formula is sometimes called the
|
||||
\index{shoelace formula} \key{shoelace formula}.} is
|
||||
\[\frac{1}{2} |\sum_{i=1}^{n-1} (p_i \times p_{i+1})| =
|
||||
\frac{1}{2} |\sum_{i=1}^{n-1} (x_i y_{i+1} - x_{i+1} y_i)|, \]
|
||||
where the vertices are
|
||||
|
|
|
@ -27,10 +27,10 @@ For example, the table
|
|||
\begin{tabular}{ccc}
|
||||
person & arrival time & leaving time \\
|
||||
\hline
|
||||
Uolevi & 10 & 15 \\
|
||||
Maija & 6 & 12 \\
|
||||
Kaaleppi & 14 & 16 \\
|
||||
Liisa & 5 & 13 \\
|
||||
John & 10 & 15 \\
|
||||
Maria & 6 & 12 \\
|
||||
Peter & 14 & 16 \\
|
||||
Lisa & 5 & 13 \\
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
corresponds to the following events:
|
||||
|
@ -51,10 +51,10 @@ corresponds to the following events:
|
|||
\draw[fill] (5,-5.5) circle [radius=0.05];
|
||||
\draw[fill] (13,-5.5) circle [radius=0.05];
|
||||
|
||||
\node at (2,-1) {Uolevi};
|
||||
\node at (2,-2.5) {Maija};
|
||||
\node at (2,-4) {Kaaleppi};
|
||||
\node at (2,-5.5) {Liisa};
|
||||
\node at (2,-1) {John};
|
||||
\node at (2,-2.5) {Maria};
|
||||
\node at (2,-4) {Peter};
|
||||
\node at (2,-5.5) {Lisa};
|
||||
\end{tikzpicture}
|
||||
\end{center}
|
||||
We go through the events from left to right
|
||||
|
@ -85,10 +85,10 @@ In the example, the events are processed as follows:
|
|||
\draw[fill] (5,-5.5) circle [radius=0.05];
|
||||
\draw[fill] (13,-5.5) circle [radius=0.05];
|
||||
|
||||
\node at (2,-1) {Uolevi};
|
||||
\node at (2,-2.5) {Maija};
|
||||
\node at (2,-4) {Kaaleppi};
|
||||
\node at (2,-5.5) {Liisa};
|
||||
\node at (2,-1) {John};
|
||||
\node at (2,-2.5) {Maria};
|
||||
\node at (2,-4) {Peter};
|
||||
\node at (2,-5.5) {Lisa};
|
||||
|
||||
\path[draw,dashed] (10,0)--(10,-6.5);
|
||||
\path[draw,dashed] (15,0)--(15,-6.5);
|
||||
|
@ -122,7 +122,7 @@ The symbols $+$ and $-$ indicate whether the
|
|||
value of the counter increases or decreases,
|
||||
and the value of the counter is shown below.
|
||||
The maximum value of the counter is 3
|
||||
between Uolevi's arrival time and Maija's leaving time.
|
||||
between John's arrival time and Maria's leaving time.
|
||||
|
||||
The running time of the algorithm is $O(n \log n)$,
|
||||
because sorting the events takes $O(n \log n)$ time
|
||||
|
@ -270,7 +270,11 @@ we should find the following points:
|
|||
|
||||
This is another example of a problem
|
||||
that can be solved in $O(n \log n)$ time
|
||||
using a sweep line algorithm.
|
||||
using a sweep line algorithm\footnote{Besides this approach,
|
||||
there is also an
|
||||
$O(n \log n)$ time divide-and-conquer algorithm \cite{sha75}
|
||||
that divides the points into two sets and recursively
|
||||
solves the problem for both sets.}.
|
||||
We go through the points from left to right
|
||||
and maintain a value $d$: the minimum distance
|
||||
between two points seen so far.
|
||||
|
@ -396,21 +400,20 @@ an easy way to
|
|||
construct the convex hull for a set of points
|
||||
in $O(n \log n)$ time.
|
||||
The algorithm constructs the convex hull
|
||||
in two steps:
|
||||
in two parts:
|
||||
first the upper hull and then the lower hull.
|
||||
Both steps are similar, so we can focus on
|
||||
Both parts are similar, so we can focus on
|
||||
constructing the upper hull.
|
||||
|
||||
We sort the points primarily according to
|
||||
First, we sort the points primarily according to
|
||||
x coordinates and secondarily according to y coordinates.
|
||||
After this, we go through the points and always
|
||||
add the new point to the hull.
|
||||
After adding a point we check using cross products
|
||||
whether the tree last point in the hull turn left.
|
||||
If this holds, we remove the middle point from the hull.
|
||||
After this we keep checking the three last points
|
||||
and removing points, until the three last points
|
||||
do not turn left.
|
||||
After this, we go through the points and
|
||||
add each point to the hull.
|
||||
Always after adding a point to the hull,
|
||||
we make sure that the last line segment
|
||||
in the hull does not turn left.
|
||||
As long as this holds, we repeatedly remove the
|
||||
second last point from the hull.
|
||||
|
||||
The following pictures show how
|
||||
Andrew's algorithm works:
|
||||
|
|
215
list.tex
215
list.tex
|
@ -25,6 +25,11 @@
|
|||
On a routing problem.
|
||||
\emph{Quarterly of Applied Mathematics}, 16(1):87--90, 1958.
|
||||
|
||||
\bibitem{bec07}
|
||||
M. Beck, E. Pine, W. Tarrat and K. Y. Jensen.
|
||||
New integer representations as the sum of three cubes.
|
||||
\emph{Mathematics of Computation}, 76(259):1683--1690, 2007.
|
||||
|
||||
\bibitem{ben00}
|
||||
M. A. Bender and M. Farach-Colton.
|
||||
The LCA problem revisited. In
|
||||
|
@ -33,17 +38,46 @@
|
|||
\bibitem{ben86}
|
||||
J. Bentley.
|
||||
\emph{Programming Pearls}.
|
||||
Addison-Wesley, 1986.
|
||||
Addison-Wesley, 1999 (2nd edition).
|
||||
|
||||
\bibitem{bou01}
|
||||
C. L. Bouton.
|
||||
Nim, a game with a complete mathematical theory.
|
||||
pro \emph{Annals of Mathematics}, 3(1/4):35--39, 1901.
|
||||
|
||||
% \bibitem{bur97}
|
||||
% W. Burnside.
|
||||
% \emph{Theory of Groups of Finite Order},
|
||||
% Cambridge University Press, 1897.
|
||||
|
||||
\bibitem{cod15}
|
||||
Codeforces: On ''Mo's algorithm'',
|
||||
\url{http://codeforces.com/blog/entry/20032}
|
||||
|
||||
\bibitem{cor09}
|
||||
T. H. Cormen, C. E. Leiserson, R. L. Rivest and C. Stein.
|
||||
\emph{Introduction to Algorithms}, MIT Press, 2009 (3rd edition).
|
||||
|
||||
\bibitem{dij59}
|
||||
E. W. Dijkstra.
|
||||
A note on two problems in connexion with graphs.
|
||||
\emph{Numerische Mathematik}, 1(1):269--271, 1959.
|
||||
|
||||
\bibitem{dik12}
|
||||
K. Diks et al.
|
||||
\emph{Looking for a Challenge? The Ultimate Problem Set from
|
||||
the University of Warsaw Programming Competitions}, University of Warsaw, 2012.
|
||||
|
||||
% \bibitem{dil50}
|
||||
% R. P. Dilworth.
|
||||
% A decomposition theorem for partially ordered sets.
|
||||
% \emph{Annals of Mathematics}, 51(1):161--166, 1950.
|
||||
|
||||
% \bibitem{dir52}
|
||||
% G. A. Dirac.
|
||||
% Some theorems on abstract graphs.
|
||||
% \emph{Proceedings of the London Mathematical Society}, 3(1):69--81, 1952.
|
||||
|
||||
\bibitem{edm65}
|
||||
J. Edmonds.
|
||||
Paths, trees, and flowers.
|
||||
|
@ -54,6 +88,11 @@
|
|||
Theoretical improvements in algorithmic efficiency for network flow problems.
|
||||
\emph{Journal of the ACM}, 19(2):248--264, 1972.
|
||||
|
||||
\bibitem{eve75}
|
||||
S. Even, A. Itai and A. Shamir.
|
||||
On the complexity of time table and multi-commodity flow problems.
|
||||
\emph{16th Annual Symposium on Foundations of Computer Science}, 184--193, 1975.
|
||||
|
||||
\bibitem{fan94}
|
||||
D. Fanding.
|
||||
A faster algorithm for shortest-path -- SPFA.
|
||||
|
@ -69,21 +108,26 @@
|
|||
Theoretical and practical improvements on the RMQ-problem, with applications to LCA and LCE.
|
||||
In \emph{Annual Symposium on Combinatorial Pattern Matching}, 36--48, 2006.
|
||||
|
||||
\bibitem{fis11}
|
||||
J. Fischer and V. Heun.
|
||||
Space-efficient preprocessing schemes for range minimum queries on static arrays.
|
||||
\emph{SIAM Journal on Computing}, 40(2):465--492, 2011.
|
||||
|
||||
\bibitem{flo62}
|
||||
R. W. Floyd
|
||||
Algorithm 97: shortest path.
|
||||
\emph{Communications of the ACM}, 5(6):345, 1962.
|
||||
|
||||
\bibitem{for56a}
|
||||
L. R. Ford.
|
||||
Network flow theory.
|
||||
RAND Corporation, Santa Monica, California, 1956.
|
||||
|
||||
\bibitem{for56}
|
||||
L. R. Ford and D. R. Fulkerson.
|
||||
Maximal flow through a network.
|
||||
\emph{Canadian Journal of Mathematics}, 8(3):399--404, 1956.
|
||||
|
||||
\bibitem{fre77}
|
||||
R. Freivalds.
|
||||
Probabilistic machines can use less running time.
|
||||
In \emph{IFIP congress}, 839--842, 1977.
|
||||
|
||||
\bibitem{gal14}
|
||||
F. Le Gall.
|
||||
Powers of tensors and fast matrix multiplication.
|
||||
|
@ -106,13 +150,58 @@
|
|||
\emph{2014 IEEE 55th Annual Symposium on Foundations of Computer Science},
|
||||
621--630, 2014.
|
||||
|
||||
\bibitem{gru39}
|
||||
P. M. Grundy.
|
||||
Mathematics and games.
|
||||
\emph{Eureka}, 2(5):6--8, 1939.
|
||||
|
||||
\bibitem{gus97}
|
||||
D. Gusfield.
|
||||
\emph{Algorithms on Strings, Trees and Sequences:
|
||||
Computer Science and Computational Biology},
|
||||
Cambridge University Press, 1997.
|
||||
|
||||
% \bibitem{hal35}
|
||||
% P. Hall.
|
||||
% On representatives of subsets.
|
||||
% \emph{Journal London Mathematical Society} 10(1):26--30, 1935.
|
||||
|
||||
\bibitem{hal13}
|
||||
S. Halim and F. Halim.
|
||||
\emph{Competitive Programming 3: The New Lower Bound of Programming Contests}, 2013.
|
||||
|
||||
\bibitem{hel62}
|
||||
M. Held and R. M. Karp.
|
||||
A dynamic programming approach to sequencing problems.
|
||||
\emph{Journal of the Society for Industrial and Applied Mathematics}, 10(1):196--210, 1962.
|
||||
|
||||
\bibitem{hie73}
|
||||
C. Hierholzer and C. Wiener.
|
||||
Über die Möglichkeit, einen Linienzug ohne Wiederholung und ohne Unterbrechung zu umfahren.
|
||||
\emph{Mathematische Annalen}, 6(1), 30--32, 1873.
|
||||
|
||||
\bibitem{hoa61a}
|
||||
C. A. R. Hoare.
|
||||
Algorithm 64: Quicksort.
|
||||
\emph{Communications of the ACM}, 4(7):321, 1961.
|
||||
|
||||
\bibitem{hoa61b}
|
||||
C. A. R. Hoare.
|
||||
Algorithm 65: Find.
|
||||
\emph{Communications of the ACM}, 4(7):321--322, 1961.
|
||||
|
||||
\bibitem{hop71}
|
||||
J. E. Hopcroft and J. D. Ullman.
|
||||
A linear list merging algorithm.
|
||||
Technical report, Cornell University, 1971.
|
||||
|
||||
\bibitem{hor74}
|
||||
E. Horowitz and S. Sahni.
|
||||
Computing partitions with applications to the knapsack problem.
|
||||
\emph{Journal of the ACM}, 21(2):277--292, 1974.
|
||||
|
||||
\bibitem{huf52}
|
||||
D. A. Huffman.
|
||||
A method for the construction of minimum-redundancy codes.
|
||||
\emph{Proceedings of the IRE}, 40(9):1098--1101, 1952.
|
||||
|
||||
|
@ -125,44 +214,140 @@
|
|||
Efficient randomized pattern-matching algorithms.
|
||||
\emph{IBM Journal of Research and Development}, 31(2):249--260, 1987.
|
||||
|
||||
\bibitem{kas61}
|
||||
P. W. Kasteleyn.
|
||||
The statistics of dimers on a lattice: I. The number of dimer arrangements on a quadratic lattice.
|
||||
\emph{Physica}, 27(12):1209--1225, 1961.
|
||||
\bibitem{kle05}
|
||||
J. Kleinberg and É. Tardos.
|
||||
\emph{Algorithm Design}, Pearson, 2005.
|
||||
|
||||
% \bibitem{kas61}
|
||||
% P. W. Kasteleyn.
|
||||
% The statistics of dimers on a lattice: I. The number of dimer arrangements on a quadratic lattice.
|
||||
% \emph{Physica}, 27(12):1209--1225, 1961.
|
||||
|
||||
\bibitem{knu982}
|
||||
D. E. Knuth.
|
||||
\emph{The Art of Computer Programming. Volume 2: Seminumerical Algorithms}, Addison–Wesley, 1998 (3rd edition).
|
||||
|
||||
\bibitem{knu983}
|
||||
D. E. Knuth.
|
||||
\emph{The Art of Computer Programming. Volume 3: Sorting and Searching}, Addison–Wesley, 1998 (2nd edition).
|
||||
|
||||
% \bibitem{kon31}
|
||||
% D. Kőnig.
|
||||
% Gráfok és mátrixok.
|
||||
% \emph{Matematikai és Fizikai Lapok}, 38(1):116--119, 1931.
|
||||
|
||||
\bibitem{kru56}
|
||||
J. B. Kruskal.
|
||||
On the shortest spanning subtree of a graph and the traveling salesman problem.
|
||||
\emph{Proceedings of the American Mathematical Society}, 7(1):48--50, 1956.
|
||||
|
||||
\bibitem{lev66}
|
||||
V. I. Levenshtein.
|
||||
Binary codes capable of correcting deletions, insertions, and reversals.
|
||||
\emph{Soviet physics doklady}, 10(8):707--710, 1966.
|
||||
|
||||
\bibitem{mai84}
|
||||
M. G. Main and R. J. Lorentz.
|
||||
An $O(n \log n)$ algorithm for finding all repetitions in a string.
|
||||
\emph{Journal of Algorithms}, 5(3):422--432, 1984.
|
||||
|
||||
% \bibitem{ore60}
|
||||
% Ø. Ore.
|
||||
% Note on Hamilton circuits.
|
||||
% \emph{The American Mathematical Monthly}, 67(1):55, 1960.
|
||||
|
||||
\bibitem{pac13}
|
||||
J. Pachocki and J. Radoszweski.
|
||||
Where to use and how not to use polynomial string hashing.
|
||||
\emph{Olympiads in Informatics}, 2013.
|
||||
\emph{Olympiads in Informatics}, 7(1):90--100, 2013.
|
||||
|
||||
% \bibitem{pic99}
|
||||
% G. Pick.
|
||||
% Geometrisches zur Zahlenlehre.
|
||||
% \emph{Sitzungsberichte des deutschen naturwissenschaftlich-medicinischen Vereines
|
||||
% für Böhmen "Lotos" in Prag. (Neue Folge)}, 19:311--319, 1899.
|
||||
|
||||
\bibitem{pea05}
|
||||
D. Pearson.
|
||||
A polynomial-time algorithm for the change-making problem.
|
||||
\emph{Operations Research Letters}, 33(3):231--234, 2005.
|
||||
|
||||
\bibitem{pri57}
|
||||
R. C. Prim.
|
||||
Shortest connection networks and some generalizations.
|
||||
\emph{Bell System Technical Journal}, 36(6):1389--1401, 1957.
|
||||
|
||||
% \bibitem{pru18}
|
||||
% H. Prüfer.
|
||||
% Neuer Beweis eines Satzes über Permutationen.
|
||||
% \emph{Arch. Math. Phys}, 27:742--744, 1918.
|
||||
|
||||
\bibitem{q27}
|
||||
27-Queens Puzzle: Massively Parallel Enumeration and Solution Counting.
|
||||
\url{https://github.com/preusser/q27}
|
||||
|
||||
\bibitem{sha75}
|
||||
M. I. Shamos and D. Hoey.
|
||||
Closest-point problems.
|
||||
\emph{16th Annual Symposium on Foundations of Computer Science}, 151--162, 1975.
|
||||
|
||||
\bibitem{sha81}
|
||||
M. Sharir.
|
||||
A strong-connectivity algorithm and its applications in data flow analysis.
|
||||
\emph{Computers \& Mathematics with Applications}, 7(1):67--72, 1981.
|
||||
|
||||
\bibitem{ski08}
|
||||
S. S. Skiena.
|
||||
\emph{The Algorithm Design Manual}, Springer, 2008 (2nd edition).
|
||||
|
||||
\bibitem{ski03}
|
||||
S. S. Skiena and M. A. Revilla.
|
||||
\emph{Programming Challenges: The Programming Contest Training Manual},
|
||||
Springer, 2003.
|
||||
|
||||
\bibitem{spr35}
|
||||
R. Sprague.
|
||||
Über mathematische Kampfspiele.
|
||||
\emph{Tohoku Mathematical Journal}, 41:438--444, 1935.
|
||||
|
||||
\bibitem{sta06}
|
||||
P. Stańczyk.
|
||||
\emph{Algorytmika praktyczna w konkursach Informatycznych},
|
||||
MSc thesis, University of Warsaw, 2006.
|
||||
|
||||
\bibitem{str69}
|
||||
V. Strassen.
|
||||
Gaussian elimination is not optimal.
|
||||
\emph{Numerische Mathematik}, 13(4):354--356, 1969.
|
||||
|
||||
\bibitem{tem61}
|
||||
H. N. V. Temperley and M. E. Fisher.
|
||||
Dimer problem in statistical mechanics -- an exact result.
|
||||
\emph{Philosophical Magazine}, 6(68):1061--1063, 1961.
|
||||
\bibitem{tar75}
|
||||
R. E. Tarjan.
|
||||
Efficiency of a good but not linear set union algorithm.
|
||||
\emph{Journal of the ACM}, 22(2):215--225, 1975.
|
||||
|
||||
\bibitem{tar84}
|
||||
R. E. Tarjan and U. Vishkin.
|
||||
Finding biconnected componemts and computing tree functions in logarithmic parallel time.
|
||||
\emph{25th Annual Symposium on Foundations of Computer Science}, 12--20, 1984.
|
||||
|
||||
% \bibitem{tem61}
|
||||
% H. N. V. Temperley and M. E. Fisher.
|
||||
% Dimer problem in statistical mechanics -- an exact result.
|
||||
% \emph{Philosophical Magazine}, 6(68):1061--1063, 1961.
|
||||
|
||||
\bibitem{war23}
|
||||
H. C. von Warnsdorf.
|
||||
\emph{Des Rösselsprunges einfachste und allgemeinste Lösung}.
|
||||
Schmalkalden, 1823.
|
||||
|
||||
\bibitem{war62}
|
||||
S. Warshall.
|
||||
A theorem on boolean matrices.
|
||||
\emph{Journal of the ACM}, 9(1):11--12, 1962.
|
||||
|
||||
% \bibitem{zec72}
|
||||
% E. Zeckendorf.
|
||||
% Représentation des nombres naturels par une somme de nombres de Fibonacci ou de nombres de Lucas.
|
||||
% \emph{Bull. Soc. Roy. Sci. Liege}, 41:179--182, 1972.
|
||||
|
||||
\end{thebibliography}
|
|
@ -12,7 +12,7 @@ The book is especially intended for
|
|||
students who want to learn algorithms and
|
||||
possibly participate in
|
||||
the International Olympiad in Informatics (IOI) or
|
||||
the International Collegiate Programming Contest (ICPC).
|
||||
in the International Collegiate Programming Contest (ICPC).
|
||||
Of course, the book is also suitable for
|
||||
anybody else interested in competitive programming.
|
||||
|
||||
|
|
Loading…
Reference in New Issue