Hi-
Breaking the calling number down by state is not too big of a deal, but needing each city will get pretty large. Maintaining it may be less cumbersome than you think as NPA / NXXs don't change that often.
If you don't receive calls from all over the country or world you may be able to reduce the amount of data you need by leaving out regions you don't typically service. Is the customer servicing all of the US?
I wrote a script that is running as a subflow that breaks down a +E.164 number and determine its country of origin as well as the State / Province if it's in North America. If the zone of the calling number is one then I evaluate the NPA and look it up in the xml document. If the zone is 2-9 I have logic to determine the country code and go from there.
North America example:
<zone zone="1">
<countrycode code="1">
<areacode NPA="218">
<state>MN</state>
<country>USA</country>
</areacode>
</countrycode>
</zone>
The entire xml document is about 5000 lines in my implementation. I really should spend some time to optimize it.
DJ