Between the two approaches you mentioned, I would be
extremely surprised if the hash did not turn out to be more efficient, as it doesn't have to step through a list of thousands of
elsifs. It also has the advantage of taking constant time regardless of whether the string is found or not, rather than being very quick if the string is at the start of the
elsif chain and being slower for a non-matching string, which would have to individually check every item in the list before it can be known that the string isn't there.
More importantly, though, the hash approach is much more readable than an endless list of elsifs, and it also opens up the possibility of storing your list of items to match against in a config file or a database (since a hash's contents are just data, not code) which will make for easier long-term maintenance.
BTW, the syntax you probably want for checking whether a hash key exists is exists($hash{$string}), not defined (which will return false if the key is there but has no value).