3

I have written following dp code today, it worked fine as it got some points in for submission (here is the problem). However I am not able to determine the running time of my code. I feel like its O(n^2 * log D) but I can't prove it.

class Solution {
public:
    unordered_map<string, bool> m;
    bool wordBreak(string s, unordered_set<string>& wordDict) {
        int n = s.length();
        string t = "";
        for(int i=0;i<n;i++){
            t += s.at(i);
            //cout << t << endl;
            if(wordDict.find(t) != wordDict.end()){
                m[t] = true;
                string x = "";
                for(int j=i+1;j<n;j++){
                    x += s.at(j);
                }
                if(x == ""){
                    return true;
                }
                if(m.find(x) != m.end()){
                    if(m[x] == true){
                        return true;
                    }else{
                        continue;
                    }
                }else{
                    if(wordBreak(x, wordDict)){
                        m[x] = true;
                        return true;
                    }else{
                        //cout << x << endl;
                        m[x] = false;
                        continue;
                    }
                }
            }else{
                //m[t] = false;
            }
        }
        return false;
    }
};
Ryan Fung
  • 2,069
  • 9
  • 38
  • 60
codeomnitrix
  • 4,179
  • 19
  • 66
  • 102
  • Typically measuring this involves either instrumenting the code will counters to see how many times you do a certain thing in the code (iterations, comparisons, etc) with varying values of `N`, `D` etc, and plot the results in a graph of the result, or do the same but measure the time the execution takes with varying values of `N` and `D`. Also `O(x)` gives "the dominant `x`", so unless `log D` is very large, and N is small, `N^2` will dominate, so the value is `O(N^2)`, even if there, tehchnically is a `* log D` involved). – Mats Petersson Sep 30 '15 at 08:00

3 Answers3

1

First of all I would rewrite is as follows (untested):

class Solution {
public:
    unordered_map<string, bool> m;
    bool wordBreak(string s, unordered_set<string>& wordDict) 
    {
        while (!s.empty())
        {
        int n = s.size() ;
        for(int i=0;i<n;i++){
            //cout << t << endl;
            if(wordDict.find(s.substr(0, i)) != wordDict.end()){
                m[t] = true;
                s = s.substr(i) ;
                break ;
        }
        return !m.empty();
    }
};

The basic idea is that once you find a match then you can remove the matching part from the string. Then I would say it's n * logD. After all you make just one pass on the for loop. Assuming you find a match at m < n then you get a new loop over (n-m).

marom
  • 5,064
  • 10
  • 14
  • `s.substr(0, i)` - this operation is `O(i)` and you do it for all `0 <= i < N`. So its `O(n^2)` in total. – piotrekg2 Sep 30 '15 at 08:49
1

It seems to have O(n*n) complexity. You use memorisation and every step of your alrotithm produce at least 1 new value in m. There is n*n/2 substrings in any string, so you will find solution for entire string with n*n/2 passages in worst case.

PS: consider unordered_map works with O(1).

EDIT:

It might be more properly to consider unordered_map works with O(n) in your case. m.find will need to calculate hash for it's argument, wich is string. may be it will work faster if you store indexes instead of string itself.

light_keeper
  • 627
  • 5
  • 15
1

Here is how I solved it.

bool wordBreak(string s, unordered_set<string>& wordDict) {
    if (s.empty()) return true;

    vector<bool> dp(s.size(), false);
    for (int i = 0; i < dp.size(); ++i)
    {
        for (int j = i; j >= 0; --j)
        {
            if (wordDict.find(s.substr(j, i - j + 1)) != wordDict.end() &&
                (j == 0 || dp[j - 1]))
            {
                dp[i] = true;
                break;
            }
        }
    }

    return dp.back();
}
piotrekg2
  • 1,237
  • 11
  • 21