To save content items to your account,
please confirm that you agree to abide by our usage policies.
If this is the first time you use this feature, you will be asked to authorise Cambridge Core to connect with your account.
Find out more about saving content to .
To save content items to your Kindle, first ensure no-reply@cambridge.org
is added to your Approved Personal Document E-mail List under your Personal Document Settings
on the Manage Your Content and Devices page of your Amazon account. Then enter the ‘name’ part
of your Kindle email address below.
Find out more about saving to your Kindle.
Note you can select to save to either the @free.kindle.com or @kindle.com variations.
‘@free.kindle.com’ emails are free but can only be saved to your device when it is connected to wi-fi.
‘@kindle.com’ emails can be delivered even when you are not connected to wi-fi, but note that service fees apply.
Because the concept of a graph was introduced to represent how objects are connected, it is not surprising that connectivity has been a central notion in graph theory since its birth in the 18th century. Various definitions of connectivities have been proposed, for example, edge-connectivity, vertex-connectivity, and their ramifications. Closely related to connectivity are flows and cuts in graphs, where the cut may be regarded as a dual concept of connectivity and flows.
A recent general trend in the research of graph theory appears as a shift to its algorithmic aspects, and improving time and space complexities has been a strong incentive for devising new algorithms. This is also true for topics related to connectivities, flows, and cuts, and much important progress has been made. Such topics include computation, enumeration, and representation of all minimum cuts and small cuts; new algorithms to augment connectivity of a given graph; their generalization to more abstract mathematical systems; and so forth. In view of these, it would be a timely attempt to summarize those results and present them in a unified setting so that they can be systematically understood and can be applied to other related fields.
In these developments, we observe that a simple tool known as maximum adjacency (MA) ordering has been a profound influence on the computational complexity of algorithms for a number of problems. It is defined as follows.
The problem of increasing edge or vertex-connectivity of a given graph up to a specified target value k by adding the smallest number of new edges is called connectivity augmentation. These problems were first studied in 1976 by Eswaran and Tarjan [64] and Plesnik [275] and were shown to be polynomially solvable for k = 2. The problems have important applications such as the network construction problem [279], the rigidity problem in grid frameworks [13, 99], the data security problem [110, 172], and the rectangular dual graph problem in floor planning [303]. We refer to [81, 241] surveys for this study.
In this chapter, we mainly treat the edge-connectivity augmentation problem for a given target value k. For a general k, Watanabe and Nakamura [308] established in 1987 a min-max theorem, based on which they gave an O(k2(kn + m)n4) time algorithm. Afterward, Frank [78] gave a unified approach to various edgeconnectivity augmentation problems by making use of the edge-splitting theorems of Lovász [200, 202] and Mader [206, 208]. Then Nagamochi and Ibaraki [236] proposed an O((nm + n2 log n) log n) time algorithm by combining the minimumcut algorithm in Section 3.2 and the approach of Frank. If the graph under consideration is weighted by real numbers, this algorithm can be further simplified and can be extended to solve the edge-connectivity augmentation problem for the entire range of target k in O(nm + n2 log n) time [238], as will be explained in Section 8.4. By using extreme vertex sets in Section 1.5.3, Benczúr and Karger [20] gave an O(n2 log5n) time randomized algorithm of Monte Carlo type to optimally increase a multigraph.
Up to now we have described many specific data structures. There are also some general methods that add some additional capabilities or properties to a given data structure. Without any further knowledge about the structure, there is not much we can do, so in each case we need some further assumptions about the operation supported by the structure or its implementation. The two well-studied problems here are how to make a static structure dynamic and how to allow queries in old states of a dynamic data structure.
Making Structures Dynamic
Several of the structures we have discussed were static structures, like the interval trees: they are built once and then allow queries, but no changes of the underlying data. To make them dynamic, we want to allow changes in the underlying data. In this generality, there is not much we can do, but with some further assumptions, there are efficient construction methods that take the static data structure as a black box, which is used to build the new dynamic structure.
The most important such class is the decomposable searching problems. Here, the underlying abstract object is some set X, and in our queries we wish to evaluate some function f(X, query), and this function has the property that for any partition X = X1 ∪ X2, the function value f(X, query) can be constructed from f(X1, query) and f(X2, query).
A search tree is a structure that stores objects, each object identified by a key value, in a tree structure. The key values of the objects are from a linearly ordered set (typically integers); two keys can be compared in constant time and these comparisons are used to guide the access to a specific object by its key. The tree has a root, where any search starts, and then contains in each node some key value for comparison with the query key, so one can go to different next nodes depending on whether the query key is smaller or larger than the key in the node until one finds a node that contains the right key.
This type of tree structure is fundamental to most data structures; it allows many variations and is also a building block for most more complex data structures. For this reason we will discuss it in great detail.
Search trees are one method to implement the abstract structure called dictionary. A dictionary is a structure that stores objects, identified by keys, and supports the operations find, insert, and delete. A search tree usually supports at least these operations of a dictionary, but there are also other ways to implement a dictionary, and there are applications of search trees that are not primarily dictionaries.
Two Models of Search Trees
In the outline just given, we supressed an important point that at first seems trivial, but indeed it leads to two different models of search trees, either of which can be combined with much of the following material, but one of which is strongly preferable.
The concept of extreme vertex sets, defined in Section 1.5.3, was first introduced by Watanabe and Nakamura [308] to solve the edge-connectivity augmentation problem. The fastest deterministic algorithm currently known for computing all extreme vertex sets was given by Naor, Gusfield, and Martel [259]. Their algorithm first computes the Gomory–Hu cut tree of the graph and then finds all maximal k-edge-connected components for some k, from which all extreme vertex sets are identified by Lemma 1.42, taking O(n(mn log(n2/m)) running time. Bencz&úr and Karger [20] have given a Monte Carlo–type randomized algorithm, which runs in O(n2 log5n) time but is rather involved. Notice that computing all extreme vertex sets is not easier than finding a minimum cut since at least one of the extreme vertex sets is a minimum cut.
In this chapter, we give a simple and efficient algorithm for computing all extreme vertex sets in a given graph, and we show some applications of extreme vertex sets. The algorithm will be used to solve the edge-connectivity augmentation problem in Section 8.3. In Section 6.1,we design a deterministic O(nm + n2 log n) time algorithm for computing the family χ(G) of extreme vertex sets in a given edge-weighted graph G, which is a laminar family, as observed in Lemma 1.41. As a new application of extreme vertex sets, in Section 6.2 we consider a dynamic graph G in which the weight of edges incident to a designated vertex may increase or decrease with time and we give a dynamic minimum cut algorithm that reports a minimum cut of the current G whenever the weight of an edge is updated.
This is a textbook for a second course on formal languages and automata theory.
Many undergraduates in computer science take a course entitled “Introduction to Theory of Computing,” in which they learn the basics of finite automata, pushdown automata, context-free grammars, and Turing machines. However, few students pursue advanced topics in these areas, in part because there is no really satisfactory textbook.
For almost 20 years I have been teaching such a second course for fourth-year undergraduate majors and graduate students in computer science at the University of Waterloo: CS 462/662, entitled “Formal Languages and Parsing.” For many years we used Hopcroft and Ullman's Introduction to Automata Theory, Languages, and Computation as the course text, a book that has proved very influential. (The reader will not have to look far to see its influence on the present book.)
In 2001, however, Hopcroft and Ullman released a second edition of their text that, in the words of one professor, “removed all the good parts.” In other words, their second edition is geared toward second- and third-year students, and omits nearly all the advanced topics suitable for fourth-year students and beginning graduate students.
Because the first edition of Hopcroft and Ullman's book is no longer easily available, and because I have been regularly supplementing their book with my own handwritten course notes, it occurred to me that it was a good time to write a textbook on advanced topics in formal languages.
In this chapter we investigate methods for parsing and recognition in contextfree grammars (CFGs). Both problems have significant practical applications. Parsing, for example, is an essential feature of a compiler, which translates from one computer language (the “source”) to another (the “target”). Typically, the source is a high-level language, while the target is machine language.
The first compilers were built in the early 1950s. Computing pioneer Grace Murray Hopper built one at Remington Rand during 1951–1952. At that time, constructing a compiler was a black art that was very time consuming. When John Backus led the project that produced a FORTRAN compiler in 1955–1957, it took 18 person-years to complete.
Today, modern parser generators, such as Yacc (which stands for “yet another compiler-compiler”) and Bison, allow a single person to construct a compiler in a few hours or days. These tools are based on LALR(1) parsing, a variant of one of the parsing methods we will discuss here. Parsing is also a feature of natural language recognition systems.
In Section 5.1 we will see how to accomplish parsing in an arbitrary CFG in polynomial time. More precisely, if the grammar G is in Chomsky normal form, we can parse an arbitrary string w ∈ L(G) of length n in O(n3) time. While a running time of O(n3) is often considered tractable in computer science, as programs get bigger and bigger, it becomes more and more essential that parsing be performed in linear time.
This paper develops a new framework for fusion that is designed for eliminating the intermediate data structures involved in the composition of functions that have one accumulating parameter. The new fusion framework comprises two steps: algebraic fusion and its subsequent improvement process. The key idea in our development is to regard functions with an accumulating parameter as functions that operate over the monoid of data contexts. Algebraic fusion composes each such function with a monoid homomorphism that is derived from the definition of the consumer function to obtain a higher-order function that computes over the monoid of endofunctions. The transformation result may be further refined by an improvement process, which replaces the operation over the monoid of endofunctions (i.e., function closures) with another monoid operation over a monoid structure other than function closures.
Using our framework, one can formulate a particular solution to the fusion problem by devising appropriate monoids and monoid homomorphisms. This provides a unified exposition of a variety of fusion methods that have been developed so far in different formalisms. Furthermore, the cleaner formulation makes it possible to argue about some delicate issues on a firm mathematical basis. We demonstrate that algebraic fusion and improvement in the world of complete pointed partial orders (CPOs) and continuous functions can correctly fuse functions that operate on partial and infinite data structures. We also show that subtle differences in termination behaviours of transformed programmes caused by certain different fusion methods can be cleanly explained by corresponding improvement processes that have different underlying monoid structures.