0

Hi I'm practicing for my interview and I would like to know if there is a better solution for this problem:

Given a key String key="apple" and a sorted Array of strings, String[] words ={apple, apples, bananaaple, orangebanana, pearapples}

write a function which return true when you can concatenate to get the key string using words from the word list, false if you can't.

my idea is starting with one letter from the key string, and do a binary search from the world list, if exists, find the rest of the string; if not, increase one more letter, and do the same.

my code:

 public static void main(String[] args){
        String[] words = {"apple", "apples", "bananaaple", "orangebanana", "pearapples"};

        String key = "apple";

        System.out.println(expanding(words,key));
    }


    public static boolean expanding(String[] words, String key){
        if(key.length()<1){
            return false;
        }

        for(int i=1; i<=key.length(); i++){
            String sub = key.substring(0, i);
            boolean found =search(words,sub,0,words.length-1);
            if(found){ //get next piece
                String theSubString =key.substring(i, key.length());
                if(theSubString.compareToIgnoreCase("")==0){
                    return found;
                }
                boolean re = expanding(words,theSubString );
                if(re)
                    return true;
            }
        }
        return false;
    }

    public static boolean search(String[] list, String key, int min, int max){
        if(min>max){
            return false;
        }
            int mid = (min+max)/2;
            if(list[mid].compareToIgnoreCase(key)==0){
                return true;
            }else if(list[mid].compareToIgnoreCase(key)<0){
                return search(list,key,mid+1,max);
            }else{
                return search(list,key,min,mid-1);
            }

    }

In my opinion the best case should be O(log n), but not sure the worst case... maybe O(n^2) when can only match one letter at a time.

can anyone give me more ideas?

3
  • I am not understanding one step in the algo above. If a letter from the key string is not found in the words list, then should we not fail the search right away? Please clarify.
    – lsk
    Commented May 16, 2013 at 5:29
  • when the a letter is not found, will try to increase the key's substring. like first with "a" then "ap" then "app" ... etc
    – Yichz
    Commented May 16, 2013 at 15:02
  • sorry didn't understand your question, but I think @Dukeling already gave your the answer
    – Yichz
    Commented May 16, 2013 at 15:11

2 Answers 2

2

Basically the approach that you put forth is a recursive search with backtracking. It should work correctly, but there should exist inputs that can make your algorithm run in exponential time.

Perhaps surprisingly, your problem can be solved in linear time using regular expressions. In your example, we would test whether the regular expression /(apple|apples|bananaaple|orangebanana|pearapples)*/ matches the key.

The problem of matching a string to a regular expression is studied in automata theory, and can be solved using a nondeterministic finite automaton in linear time.

5
  • Actually, it's any finite automaton, as an NFA can be converted to a DFA
    – hd1
    Commented May 16, 2013 at 0:25
  • Yup. I omitted that point for simplicity, since I think NFAs are easier to implement for regexes.
    – Nayuki
    Commented May 16, 2013 at 0:27
  • @NayukiMinase Minase: Great answer.
    – Steve P.
    Commented May 16, 2013 at 0:27
  • @hd1: you can convert it to a DFA, but the runtime, can, and in this case, will be different!
    – Steve P.
    Commented May 16, 2013 at 0:28
  • I wish I can improve on my answer, because it's not particularly constructive. I can't seem to concisely explain how to implement an NFA for this problem and justify that it works.
    – Nayuki
    Commented May 16, 2013 at 0:31
0

Can we have a Trie where all the words in the word list are inserted?

  • We can take the entire key word, one letter at a time until we reach the LEAF of the trie.
  • On reaching a LEAF, we have found one portion of the key word.
  • Continue TRIE search all remaining letters/sub-words in the key word.
  • If we reach the end of the key word && reach LEAF at the same time in the TRIE, then we have a match using a combination of words in the TRIE.
1
  • 1
    What if we have {apple, apples, pie}? apple won't end at a leaf so it won't match applepie. You'll need an end-flag at each node. Also, what then for {apple, apples, steak}? If given apples..., do we match apple and first letter of steak or apples? So you'd likely have to split and check all possibilities. Commented May 16, 2013 at 7:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.