Automata and Formal Languages: An Introduction