8

This is an interview question:

Given a string, find all its permutations that are a word in dictionary.

My solution:

Put all words of the dictionary into a suffix tree and then search each permutation of the string in the tree.

The search time is O(n), where n is the size of the string. But the string may have n! permutations.

How do I improve the efficiency?

Blender
  • 289,723
  • 53
  • 439
  • 496
user1002288
  • 4,860
  • 10
  • 50
  • 78
  • 2
    The usual name for this task is finding anagrams—there's a classic approach that you should be able to find with that search term. – Per Dec 08 '11 at 04:36

6 Answers6

9

Your general approach isn't bad.

However, you can prevent having to search for each permutation by rearranging your word so that all it's characters are in alphabetical order, then searching on a dictionary where each word is similarly re-arranged into alphabetical order and mapped to the original word.

I realise that might be a little hard to grasp as is, so here's an example. Say your word is leap. Rearrange this to aelp.

Now in your dictionary you might have the words plea and pale. Having done as suggested, your dictionary will (among other things) contain the following mappings:

...
aelp -> pale
aelp -> plea
...

So now, to find your anagrams you need only find entries for aelp (using, for example, a suffix-tree approach as suggested), rather than for all 4! = 24 permutations of leap.

Mac
  • 14,615
  • 9
  • 62
  • 80
  • this my analysis for you idea. Sort each word in the dictionary. O(n * m * lg m), n is size of dictionary, m is average length of word Put each pair into a hashmap< string, list >. If key conflict, put the unsorted word into a list. This O(n). Sort the given string, O( p lg p), p is size of the string. Search the sorted string (an anagram) in the hashmap. O(1). The list of the key of the anagram is all permutations. So, totally it is O(n * m * lg m + p lg p), usually, p << n, so we have O(n * m * lg m) and space O(n). – user1002288 Dec 08 '11 at 05:35
2

A quick alternative solution - all depends on the sizes of data structures in question.

If the dictionary is reasonable small and the string is reasonably long, you can go over each entry in the dictionary and figure out if they are a permutation of the string. You can be smarter - you can sort the dictionary and skip certain entries.

Alpha01
  • 838
  • 6
  • 13
1

You can build a map from a sorted list of characters to a list of words.

For example, given these:

Array (him, hip, his, hit, hob, hoc, hod, hoe, hog, hon, hop, hos, hot)

you would sort them internally:

 Array (him, hip, his, hit, bho, cho, dho, eho, gho, hno, hop, hos, hot)

sort the result:

 Array (bho, cho, dho, eho, gho, him, hip, his, hit, hno, hop, hos, hot)

In this small sample, we don't have a match, but for a particular word, you would sort it internally, and with this as key look into your map.

user unknown
  • 35,537
  • 11
  • 75
  • 121
1

Why don't you use a hash map to store the dictionary words? So you get O(1) lookup time. And if your input is in english, you can build another table to tell all the possible letters in your dictionary, using this table, you can filter some inputs at the beginning. Following is an example:

result_list = empty;   

for(char in input)
{
   if(char not in letter_table)
   {
      return result_list;
   }
}

for(entry in permutations of input)
{
    if(entry in dictionary_hash_table)
    { 
        result_list->add_entry();
    }
}

return result_list
Shawnone
  • 850
  • 5
  • 17
1

You should put the words into a trie. Then you can look up the word as you generate the permutations. You can skip over whole blocks of permutations with the first part is not in the trie.

http://en.wikipedia.org/wiki/Trie

Fantius
  • 3,806
  • 5
  • 32
  • 49
0

Another simple solution could be as algorithm below,

1) Use "next_permutation" to find a unique permutation.

2) Use "find/find_if" to find it against a dictionary.

rakesh
  • 1,941
  • 2
  • 16
  • 23