First thing: stop worrying about normalising data and then having to use joins. That is exactly what you are supposed to do and how relational databases work. DB engines have been optimised to perform joins efficiently.
When people worry about joins etc, it is usually because they are thinking in flat-file mode. Forget everything you know about any other type of file or database processing - relational databases have nothing in common with them.
A query that joins 2 tables on properly configure integer indexes will run faster then a query on one table using a character index. In fact, it is often better to just do a table scan rather than use a character index.
That said, I belaboured the point about domain knowledge precisely because we have to think about how the data will be used and modify the schema to make that specific processing more efficient.
Now in this case, how will the search terms be entered? What is the user interface design? I would expect that users would select from combo-boxes for town then district (use AJAX or plain javascript to make that work nicely). I would certainly not just let them type any old name into a text box.
The combo-box (drop-down list) will return the integer id for town or district which is the input into your query. That will give you the most efficient processing. No queries for mis-spelled names or non-existant districts. No results for same named towns in different states, or same named districts in different towns. Fast query processing using integer ids, and the occasional join to get all companies in all districts in a given town.
So 4 tables is the way I would go. Companies table with Foriegn Key to Districts table which has Foriegn Key to towns table, which has Foriegn Key to States table (or counties table if you are here in the UK). I don't know the scope of your data, but there are 27 towns named Dover in the usa so which Dover is the user after? Likewise there are untold towns and districts with the same or very similar names in every country in the world.
PS the other reason to use integer ids is that you don't have to update multiple records when you change the data it relates to: eg District changes name, or you miss-spelled it in the first place.