Hello! Welcome back to our study of Context-Free Languages.
In our last lesson, we discovered that unlike regular languages, the class of context-free languages (CFLs) is not closed under intersection or complementation. This revealed important limitations on the computational power of pushdown automata. Today, we shift our focus to a fundamental decidable problem for CFLs: the membership problem.
This lesson directly addresses the learning outcome: Solve the membership problem for CFLs using the CYK algorithm with a grammar in CNF. Given any context-free grammar and a string , can we design an algorithm to determine if can be generated by ? The answer is yes, and the Cocke-Younger-Kasami (CYK) algorithm provides an elegant and efficient solution using dynamic programming. Your background in designing complex, multi-stage systems and your interest in algorithmic efficiency will be valuable in appreciating the structure and performance of this algorithm.
1. The Membership Problem and Its Challenges
The membership problem for CFLs is formally stated as:
Given a Context-Free Grammar (CFG) and a string , is ?
A naive approach would be to start generating all possible strings from the grammar's start symbol. However, if the language is infinite, this process may never terminate, so it isn't a viable algorithm.
A more refined approach, which we've touched on before, relies on converting the grammar to Chomsky Normal Form (CNF). A key property of a CNF grammar is that any derivation of a string of length requires exactly steps. This guarantees that we can limit our search, making the problem decidable. However, trying to check all possible derivations of that length can lead to an exponential number of possibilities, which is highly inefficient.
This is where dynamic programming comes in, providing a polynomial-time solution.
2. The Core Idea: Dynamic Programming
The CYK algorithm solves the membership problem by breaking it down into smaller, manageable subproblems. Instead of asking "Can the start symbol generate the whole string ?" from the top down, it asks from the bottom up: "Which variables can generate the various substrings of ?"
The algorithm builds a table that stores the solutions to these subproblems. For a string , we'll construct an table, let's call it , where the entry will contain the set of all variables that can generate the substring starting at position of length .
To get a clear, high-level overview of this dynamic programming strategy, please watch the following video. It explains why a grammar in CNF is crucial and how the problem of generating a string can be recursively divided into generating its constituent parts.
The CYK Algorithm: How does it work? Dynamic Programming!
This video from Easy Theory explains the foundational concepts behind the CYK algorithm. It highlights the importance of Chomsky Normal Form and introduces the dynamic programming approach of breaking the string into smaller substrings.
Watch the segments from 04:54 to 13:21. Focus on two key ideas: Why Chomsky Normal Form (CNF) is essential. How the problem of generating a long string is reduced to generating two smaller, adjacent substrings.
As the video explains, the key insight is that for a rule in CNF, if generates a substring , then must be splittable into two non-empty parts, and , such that generates and generates . The CYK algorithm systematically checks all possible splits for all substrings.
3. The CYK Algorithm: A Step-by-Step Guide
Let's formalize the algorithm. Given a CFG in CNF and an input string of length .
-
Initialization (Substrings of length 1):
For each character in the string, find all variables that have a rule . Fill the first row of our table, , with these variables. This represents all variables that can generate substrings of length 1. -
Iterative Step (Substrings of length ):
For each substring length from 2 to :
For each starting position from 1 to :- We want to compute , which corresponds to the substring .
- We consider every possible split point for this substring (where ). Each split divides the substring into two smaller parts:
- Part 1:
w[i..i+k-1](of lengthk) - Part 2:
w[i+k..i+j-1](of lengthj-k)
- Part 1:
- The variables that can generate these smaller parts have already been computed and are stored in and .
- We then check every rule of the form . If and , it means can generate the full substring
w[i..i+j-1]. We add to the set in .
-
Conclusion:
After filling the entire table, we check the top-most cell, . If the start symbol is in this set, it means can generate the entire string . The string is a member of the language. Otherwise, it is not.
A Worked Example
The process of filling the table is best understood with a concrete example. The following video provides an excellent, clear walkthrough.
Lec-63: CYK Algorithm | Membership Algorithm in CFG | TOC
This video from Gate Smashers demonstrates the CYK algorithm with a step-by-step example, showing exactly how the dynamic programming table is constructed and filled.
Watch the video from 02:09 to 15:08. The table notation in the video is slightly different (V_ij for the substring from index i to j), but the logic is identical. Follow along as the table is filled for the string aabba.
The table structure in the video is an upper-triangular matrix, where cell holds variables for the substring . This is a common and intuitive way to visualize the algorithm.

Test your understanding!
Consider the grammar in CNF:
And the input string .
Let's start filling the CYK table. What would be the contents of the cells for substrings of length 1 and length 2?
Show answer
Let the table be , where stores variables for the substring from index to . The string is .
Length 1:
- (for 'b'): From rule , we get .
- (for 'a'): From rules and , we get .
- (for 'b'): From rule , we get .
Length 2:
- (for 'ba'): Split is 'b' ('a'). This corresponds to and . We look for rules where and .
- : We have rule . So, add to .
- : We have rule . So, add to .
- Therefore, .
- (for 'ab'): Split is 'a' ('b'). This corresponds to and . We look for rules where and .
- : We have rules and . So, add to .
- : No rules.
- Therefore, .
4. Formal Algorithm and Complexity
For a more rigorous look at the algorithm, including its formal pseudocode and another detailed example, the following lecture notes are an excellent resource.
Chapter 7 Handout: CFLs are in P
These notes from NJIT provide a complete walkthrough of the CYK algorithm, including formal pseudocode and a clear complexity analysis. This is great for solidifying your understanding of the implementation details.
Read pages 51 through 68. This covers: The motivation for a dynamic programming approach. The table setup and filling logic. A detailed example with the string baaba. The formal pseudocode of the algorithm and its O(n³) complexity analysis.
As detailed in the notes, the CYK algorithm has three nested loops:
- Looping over the substring length, (from 2 to ).
- Looping over the start position, (from 1 to ).
- Looping over the split point, (from to ).
This structure leads to a time complexity of , where is the length of the string and is the size of the grammar (number of rules). Since the grammar is fixed for a given language, the complexity is typically stated as . This polynomial-time performance is a significant improvement over exponential methods and proves that every context-free language is in the complexity class P.
Conclusion
In this lesson, we tackled the fundamental membership problem for CFLs and learned a powerful and efficient algorithm to solve it.
Key Takeaways:
- The membership problem for a CFL—deciding if a string is in —is decidable.
- The CYK algorithm provides an efficient, polynomial-time solution using dynamic programming.
- A prerequisite for the algorithm is that the grammar must be in Chomsky Normal Form (CNF).
- The algorithm works by systematically building a table of which variables can generate which substrings of the input string, from length 1 up to .
- A string is in the language if and only if the start symbol is in the table cell corresponding to the entire string.
- The complexity of the CYK algorithm proves that all CFLs are in the complexity class P.
Preview of the Next Lesson:
The CYK algorithm is one of several important "decision properties" for CFLs. Having answered the membership question, we will next explore algorithms to answer other fundamental questions: Is a given CFL empty? Is it finite or infinite? These problems also have algorithmic solutions that rely on analyzing the structure of the grammar itself.