Came across this Question and took the fact that there wasn't a fully-working regex as a personal challenge. I believe I've managed to create a regex that does work for all inputs - provided you can use atomic grouping/possessive quantifiers.
Of course, I'm not sure if there are any flavours that allow atomic grouping but not lookaround, but the Question asked if it's possible in regex to state an exclusion without lookaround, and it is technically possible:
\A(?:$|[^f]++|f++(?:[^o]|$)|(?:f++o)*+(?:[^o]|$))*\Z
Explanation:
\A #Start of string
(?: #Non-capturing group
$ #Consume end-of-line. We're not in foo-mode.
|[^f]++ #Consume every non-'f'. We're not in foo-mode.
|f++(?:[^o]|$) #Enter foo-mode with an 'f'. Consume all 'f's, but only exit foo-mode if 'o' is not the next character. Thus, 'f' is valid but 'fo' is invalid.
|(?:f++o)*+(?:[^o]|$) #Enter foo-mode with an 'f'. Consume all 'f's, followed by a single 'o'. Repeat, since '(f+o)*' by itself cannot contain 'foo'. Only exit foo-mode if 'o' is not the next character following (f+o). Thus, 'fo' is valid but 'foo' is invalid.
)* #Repeat the non-capturing group
\Z #End of string. Note that this regex only works in flavours that can match $\Z
If, for whatever reason, you can use atomic grouping but not possessive quantifiers nor lookaround, you can use:
\A(?:$|(?>[^f]+)|(?>f+)(?:[^o]|$)|(?>(?:(?>f+)o)*)(?:[^o]|$))*\Z
As others point out, though, it's probably more practical to just negate a match through other means.