3.2. Regular Languages

A language S is defined to be regular if and only if there is a DFA M so that S = L(M).

For example,

{s | s ∈ {0,1}*, s is a binary number that is divisible by 3}
is a regular language.

The key observation about a regular language L is that you must be able to distinguish between a member of L and a nonmember of L by scanning the string, keeping track of only a fixed amount of information, independent of the length of the string that you are scanning.


Nonregular languages

It is easy to come up with languages that appear to require a memory that grows as the length of the input grows. For example, consider

W = {anbn | n > 0}
    = {ab, aabb, aaabbb, aaaabbbb, …}
In order to be a member of W, a string must consist of some number of a's followed by the same number of b's.

The obvious way to decide whether a string is in W is to count the number of a's and count the number of b's, then compare the two counts.

(There is also the issue of whether the string does not have an a after a b, but that is easy to add in.)

The problem is that you cannot count the number of a's with a fixed amount of memory. The count could be arbitrarily large.