I am given a input string s ("bedbathandbeyond") and a set of words {"bed", "bath", "beyond", "bat", "hand", "and"}. I need to divide the input string s into a series of words in the dictionary. In this case, the two allowed outputs would be ["bed", "bath", "and", "beyond"] and ["bed", "bat", "hand", "beyond"]. Both outputs are allowed and none is better than the other. My solution is as follows:
def find_breakdown_rec(s, dictionary, memo = {}):
    if len(s) == 0:
        return True, []
    if (s in memo):
        return memo[s]
    for i in range(len(s) + 1):
        word = s[:i]
        if word in dictionary:
            status, words = find_breakdown_rec(s[i:], dictionary, memo)
            if status:
                    memo[s] =  [word] + words
                    return True, memo[s]
    return False, []
If no memoization is used, the runtime is clearly exponential: we have O(n) branching factor, and O(n) as the depth: O(n ** n). With memoization, however, the algorithm seems to me polynomial: the 'find_breakdown_rec' can be called with n different inputs, and it then performs a polynomial amount of work on it. I've been told by a very knowledgeable person that it's still exponential. Could someone explain why? I've been thinking very hard about it and I'm not sure why that's the case.