Hello! Welcome back to our exploration of the Theory of Computation.
In our last lesson, we formally defined regular expressions as a way to describe languages using the operations of union, concatenation, and Kleene star. We saw that every regular expression corresponds to a language .
Today, we shift from interpreting regular expressions to creating them. Your goal for this lesson is to learn how to construct regular expressions for languages with specified patterns. This is the skill that bridges the gap between an abstract language description and a concrete, formal representation. Given your background in software development, especially in areas like NLP and building parsers, you've likely used regex libraries for practical pattern matching. This lesson will solidify the theoretical principles behind that practice.
A Strategy for Building Regular Expressions
Constructing a regular expression is a bit like programming: it’s a creative process of problem-solving. A good general strategy is to deconstruct the language description into its fundamental pieces and then translate those pieces into regex syntax.
- Analyze the Pattern: Read the description of the language carefully. Break it down into smaller, manageable constraints.
- What are the required, fixed parts of the strings (e.g., must start with
01, must containaa)? These often map to concatenation. - Are there choices or alternatives (e.g., starts with
aorb)? This implies union (∪). - Are parts of the string repeated zero or more times (e.g., "any number of
a's")? This calls for the Kleene star (*). - Are parts repeated one or more times? This can be handled with positive closure,
R⁺, which is shorthand forRR*.
- What are the required, fixed parts of the strings (e.g., must start with
- Translate and Combine: Convert each constraint into a small regular expression. Then, combine these smaller expressions using concatenation, union, and star operators to build the final expression. Use parentheses
()to enforce the correct order of operations. - Test and Refine: Check your regular expression against some sample strings that should be in the language (positive examples) and some that should not (negative examples). This often reveals edge cases, like the empty string , that you might have missed.
Common Patterns and Their Construction
Let's walk through some of the most common types of patterns. We'll use a video that provides numerous examples. For each pattern type, I'll explain the logic and then direct you to the relevant part of the video to see it in action.
Regular Expression Examples || Theory of Computation || Automata Theory || FLAT || Design a
This video by Sudhakar Atchala presents 15 excellent examples of constructing regular expressions. We will use it as a practical guide for different pattern types. You don't need to watch it all at once; we will refer to specific examples as we go.
Keep this video open and jump to the timestamps mentioned below as you progress through the lesson. The examples are quick and clear.
Let's assume our alphabet is or unless stated otherwise. The expression will be our go-to for "any string of a's and b's".
1. Patterns Based on Prefixes, Suffixes, and Substrings
These are some of the most straightforward patterns.
-
Starts with a pattern
w: The string must begin withw, followed by anything.- Regex:
w(a \cup b)^* - Example (starts with 1, ends with 0): Watch the video from 2:02 to 2:37 (Example 3). The logic is:
1(starts with 1)(0 \cup 1)^*(followed by anything)0(ends with 0). The resulting regex is1(0 \cup 1)^*0.
- Regex:
-
Ends with a pattern
w: The string must have anything at the beginning, but must end withw.- Regex:
(a \cup b)^*w - Example (ends with 00): Watch the video from 1:19 to 2:02 (Example 2). Regex:
(0 \cup 1)^*00.
- Regex:
-
Contains a pattern
was a substring:wcan appear anywhere in the string.- Regex:
(a \cup b)^*w(a \cup b)^* - Example (contains the substring
aaa): Watch the video from 10:41 to 11:04 (Example 14). Regex:(a \cup b)^*aaa(a \cup b)^*.
- Regex:
2. Patterns Based on Positional Constraints
Sometimes the position of a character is specified relative to an end of the string.
- The k-th character from the right is
a: This means after the requireda, there must be exactlyk-1more characters.- Regex Logic:
(anything) a (char) (char) ...(k-1times) - Example (3rd character from the right is
a): Watch the video from 5:31 to 6:19 (Example 7). The regex is(a \cup b)^*a(a \cup b)(a \cup b).
- Regex Logic:
Test your understanding!
Let . Construct a regular expression for the language of all strings where the second symbol is a 0 and the string contains the substring 11.
Show answer
There are two cases to consider, which suggests a union:
-
The
11substring appears after the second position. The string starts with any symbol, followed by0. After that, anything can come, as long as it contains11.- Regex:
(0 \cup 1)0(0 \cup 1)^*11(0 \cup 1)^*
- Regex:
-
The
11substring overlaps with the start. This can't happen if the second symbol must be0. The first symbol would have to be1and the second1, which violates the condition.
So, the first case is the complete solution: (0 \cup 1)0(0 \cup 1)^*11(0 \cup 1)^*.
3. Patterns Based on Counting
These patterns involve constraints on the number of occurrences of a symbol.
-
At least n occurrences: The required symbol must appear
nor more times, separated by any other characters.- Example (at least two
b's): Watch the video from 6:19 to 7:12 (Example 8). The logic is to ensure twob's appear in the string, with anything allowed before, between, and after them. - Regex:
(a \cup b)^*b(a \cup b)^*b(a \cup b)^*
- Example (at least two
-
Exactly n occurrences: This is trickier. If we want exactly two
b's, we must ensure no otherb's appear. This means the other parts of the string can only bea's.- Example (exactly two
b's): Watch the video from 7:12 to 7:57 (Example 9). - Regex:
a*ba*ba*
- Example (exactly two
-
At most n occurrences: This means the string can have 0, 1, ..., or n occurrences. We handle this with a union of the "exactly" cases.
- Example (at most two
a's): Watch the video from 9:58 to 10:41 (Example 13). The logic is to combine the expressions for exactly zeroa's (b*), exactly onea(b*ab*), and exactly twoa's (b*ab*ab*). - Regex:
b* \cup b*ab* \cup b*ab*ab*
- Example (at most two
-
Number of symbols is divisible by k: This is a classic, more advanced pattern. Let's design a regex for strings where the number of
a's is a multiple of 3 (i.e., 0, 3, 6, ...).- Logic: Strings can contain any number of
b's. Thea's must come in groups of three. Between any twoa's, there can beb's. - A block that adds exactly three
a's isab*ab*a. - We can have
b's at the start:b*. - We can repeat groups of three
a's:(b*ab*ab*a)*. - Combining these ideas, a robust expression is:
b*(ab*ab*ab*)*. This allows for leadingb's (b*), and then zero or more blocks of(ab*ab*ab*), where each block introduces exactly threea's while allowingb's in between. - Watch the video from 9:04 to 9:58 (Example 12) for a similar line of reasoning.
- Logic: Strings can contain any number of
4. Patterns of Exclusion
What if a language is defined by what it cannot contain?
- Does not contain the substring
ab: This means that if anaever appears, nobcan appear after it. The only way for this to be true is if allb's come before alla's.- Example (doesn't contain
ab): Watch the video from 11:04 to 12:02 (Example 15). - Regex:
b*a*
- Example (doesn't contain
Practical Shorthands and Real-World Examples
In practice, and in some textbooks, you'll see shorthand notations to make regular expressions more concise. You've probably used these in your coding work.
These lecture slides from Stanford nicely summarize the common shorthands used in regular expressions. This connects our formal notation to what you see in programming.
Read the slide titled 'Shorthand Summary'. It introduces R⁺, R?, and Σ.
Here's a quick summary of the most important shorthands:
R⁺(Positive Closure): One or more occurrences ofR. It's shorthand forRR*.R?(Zero or one): Zero or one occurrence ofR. It's shorthand forR ∪ ε.
The patterns we've discussed form the basis for recognizing everything from programming language syntax to file formats. The image below shows how these concepts are applied to define patterns for real-world data.

Conclusion
In this lesson, you learned to translate descriptive language requirements into formal regular expressions. This is a fundamental skill that requires breaking a problem down and methodically applying the core operators of union, concatenation, and Kleene star.
Key Takeaways:
- Decomposition is key: Break down complex language descriptions into smaller, manageable constraints.
- Master the building blocks: Understand how to represent concepts like "starts with," "contains," "at least n," and "exactly n" using combinations of
∪,*, and concatenation. - Handle tricky cases systematically: Patterns like "at most n," "divisible by k," and "does not contain" often require more careful construction using unions or thinking about what is allowed.
- Theory meets practice: The formal regular expressions we build here are the theoretical foundation for the powerful pattern-matching tools used in nearly every area of computer science.
Preview of the Next Lesson:
We've now seen two different ways to represent regular languages: finite automata (which recognize strings) and regular expressions (which describe strings). Are they equally powerful? The answer is yes, and proving it is a cornerstone of this course.
In the next lesson, we will begin building the bridge from regular expressions to automata. We will introduce a new type of automaton, the NFA with -transitions (NFA-), which is a crucial intermediate step in converting any regular expression into an equivalent finite automaton.