Yeah, that's effectively the solution using a hash table (but avoiding all of the messiness that's involved with hash tables). There's some shifty stuff that goes on with arrays in PHP. The way they are constructed in the engine depends on a bunch of stuff, including the size of the array, what you're puting into it and what you're doing with it after it's constructed. When you use an array in that fashion, it's acting like a dictionary/hash table.
To quote the PHP manual:
An array in PHP is actually an ordered map. A map is a type that maps values to keys. This type is optimized in several ways, so you can use it as a real array, or a list (vector), hashtable (which is an implementation of a map), dictionary, collection, stack, queue and probably more. Because you can have another PHP array as a value, you can also quite easily simulate trees.
Part of the requirement of the original problem (this is a Microsoft interview question, apparently. tests if you understand space/time trade-offs, maybe?) is that you write it in C (tests if you understand data structures, I guess?).
What would you use as the hash function? Since it's a pretty simple value (the pair), you can pretty trivially concoct a perfect hash function (1:1).
The solution using the graph is also pretty interesting. I'm not completely sure that you can guarantee that it's O(n) without use of O(R^2) space, though (where R is the range of characters). Just sort of thinking out loud here -- I suppose you have to do that with the hash table too, though. Depending on how the hash table is implemented (in addition to [tex]\alpha[/tex], its load factor = the number of elements / the capacity), you could contrive a string that induces a bunch of collisions and make lookups in the hash table O(n), which would make the entire thing O(n^2).
Incidentally, one of my research advisor's past topics is a the DAWG (Directed Acyclic Word Graph). It's a really interesting data structure that allows you to do efficient searches for substrings within strings and is intended to be used in things like the human genome project (where you're searching through gigabytes of data for a string that's a tiny tiny fraction of that). If you have a string of length n and a substring of length m, it takes O(mn) time to build the DAWG, but then it requires O(m) time to search for any substring of that length. The solution I thought of for this problem involving a graph is loosely related to this data structure, but it's definitely not a DAWG.