Add integer partition examples

This commit is contained in:
Antti H S Laaksonen 2017-05-02 19:49:34 +03:00
parent 5d283335e3
commit d679d78294
1 changed files with 100 additions and 0 deletions

View File

@ -309,6 +309,106 @@ so the total time needed is $O(n \sqrt n)$.
The time complexity of the algorithm is $O(n \sqrt n)$, The time complexity of the algorithm is $O(n \sqrt n)$,
because both cases take a total of $O(n \sqrt n)$ time. because both cases take a total of $O(n \sqrt n)$ time.
\section{Integer partitions}
Some square root algorithms are based on
the following observation:
if a positive integer $n$ is represented as
a sum of positive integers,
such a sum contains only $O(\sqrt n)$ \emph{distinct} numbers.
The reason for this is that a sum with
the maximum amount of distinct numbers has to be of the form
\[1+2+3+ \cdots = n.\]
The sum of the numbers $1,2,\ldots,k$ is
\[\frac{k(k+1)}{2},\]
so the maximum amount of distinct numbers is $k = O(\sqrt n)$.
Next we will discuss two problems that can be solved
efficiently using this observation.
\subsubsection{Knapsack}
Suppose that we are given a list of integer weights
whose sum is $n$.
Our task is to find out all sums that can be formed using
a subset of the weights. For example, if the weights are
$\{1,3,3\}$, the possible sums are as follows:
\begin{itemize}[noitemsep]
\item $0$ (empty set)
\item $1$
\item $3$
\item $1+3=4$
\item $3+3=6$
\item $1+3+3=7$
\end{itemize}
Using the standard knapsack approach (see Chapter 7.4),
the problem can be solved as follows:
we define a function $f(k,s)$ whose value is 1
if the sum $s$ can be formed using the first $k$ weights,
and 0 otherwise.
All values of this function can be calculated
in $O(n^2)$ time using dynamic programming.
However, we can make the algorithm more efficient
by using the fact that the sum of the weights is $n$,
which means that there are at most $O(\sqrt n)$
distinct weights.
Thus, we can process the weights in groups
such that all weights in each group are equal.
It turns out that we can process each group
in $O(n)$ time, which yields an $O(n \sqrt n)$ time algorithm.
The idea is to use an array that records the sums of weights
that can be formed using the groups processed so far.
The array contains $n$ elements: element $k$ is 1 if the sum
$k$ can be formed and 0 otherwise.
To process a group of weights, we can easily scan the array
from left to right and record the new sums of weights that
can be formed using this group and the previous groups.
\subsubsection{String construction}
Given a string and a dictionary of words,
consider the problem of counting the number of ways
the string can be constructed using the dictionary words.
For example,
if the string is \texttt{ABAB} and the dictionary is
$\{\texttt{A},\texttt{B},\texttt{AB}\}$,
there are 4 ways:
$\texttt{A}+\texttt{B}+\texttt{A}+\texttt{B}$,
$\texttt{AB}+\texttt{A}+\texttt{B}$,
$\texttt{A}+\texttt{B}+\texttt{AB}$ and
$\texttt{AB}+\texttt{AB}$.
Assume that the length of the string is $n$
and the total length of the dictionary words is $m$.
A natural way to solve the problem is to use dynamic
programming: we can define a function $f$ such that
$f(k)$ denotes the number of ways to construct a prefix
of length $k$ of the string using the dictionary words.
Using this function, $f(n)$ gives the answer to the problem.
There are several ways to calculate the values of $f$.
One method is to store the dictionary words
in a trie and go through all ways to select the
last word in each prefix, which results in an $O(n^2)$ time algorithm.
However, instead of using a trie, we can also use string hashing
and always go through the dictionary words and compare their
hash values.
The most straightforward implementation of this idea
yields an $O(nm)$ time algorithm,
because the dictionary may contain $m$ words.
However, we can make the algorithm more efficient
by considering the dictionary words grouped by their lengths.
Each group can be processed in constant time,
because all hash values of dictionary words may be stored in a set.
Since the total length of the words is $m$,
there are at most $O(\sqrt m)$ distinct word lengths
and at most $O(\sqrt m)$ groups.
Thus, the running time of the algorithm is only $O(n \sqrt m)$.
\section{Mo's algorithm} \section{Mo's algorithm}
\index{Mo's algorithm} \index{Mo's algorithm}