Now, however, we will tie all of this together. We will show that, in one sense, DFAs and NDFAs are the same. Namely, that:
For any language $L \subseteq \Sigma^*$, there is a DFA accepting $L$ if and only if there is an NDFA accepting $L$.This is huge and, I hope, unexpected. You would think that all the power that comes with nondeterminism would buy you something, but in terms of what languages can be accepted, it doesn't.
So how will we show this remarkable fact? How else? By giving an algorithm that converts an NDFA to a DFA acccepting the same language!
that we want to "convert" to a deterministic machine? The clever way to go about it is to keep track of all the different possible states you could be in for every new character you read.
| When we start, q0 is the only possible state. | ![]() |
||
| When you're in q0 and you read a, you could either go to q0 or q1. | ![]() |
When you're in q0 and you read b, you could only go to q0. | ![]() |
| When you're in q0 or q1 and you read a, you could go to either q0 or q1. | ![]() |
When you're in q0 or q1 and you read b, you could go to either q0 or q2. | ![]() |
| When you're in q0 or q2 and you read a, you could go to either q0 or q1. | ![]() |
When you're in q0 or q2 and you read b, you could only go to q0. | ![]() |
Each state of this machine is labeled with all the possible states from the original nondeterministic machine that we could be in. So if we've read aab, the fact that we're in state {q0,q2} tells us that we could be in either state q0 or q2 of the original machine, depending on which computation path we took. Now, the definition of acceptance for nondeterministic machines is that at least one of the computational paths leaves you in an accpeting state. Thus, our only accepting state would be {q0,q2}, since it's the only state that includes an accepting state from the original machine. So, our final machine is:
