LeetCode139:Word Break

题目:

Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one or more dictionary words.

For example, given
s = "leetcode",
dict = ["leet", "code"].

Return true because "leetcode" can be segmented as "leet code".

解题思路:

这是一道DP题,说实话,本人也是算法方面的菜鸟一枚,关于DP方面的题,还不太会解,没办法,只能多练习了。

这里采用DP中的两种方式实现:自顶向下和自底向上。

dp[i]表示前i个字符能否进行Wordbreak。当求解dp[i]时,可利用已经求解的dp[i-1],dp[i-2]…dp[1],dp[0]进行求解。

对于dp[n]的求解,我们可以将n个字符进行切分求解,分为前i个字符和后n-i个字符,i可以为(0,1,2,3,4…n-1)

假设i为1时,可根据dp[i]和后面的n-1个字符组成的单词是否在dict中来判断dp[n],只要i(0,1,2,3,4…n-1)其中一种

情况为真,则dp[n]为true,表示可以进行workbreak。

实现代码:

#include <iostream>

#include <string>

#include <vector>

#include <unordered_set>

using namespace std;



/*

Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one or more dictionary words.



For example, given

s = "leetcode",

dict = ["leet", "code"].



Return true because "leetcode" can be segmented as "leet code".

*/ 

class Solution {

public:

    bool wordBreak(string s, unordered_set<string> &dict) {

        if(s.size() == 0 || dict.size() == 0)

            return false;

        int len = s.size();

        vector<bool> dp(len+1, false);//保存状态,dp[i]表示前i个字符是否可以进行wordBread 

        dp[0] = true;

        for(int i = 1; i <= len; i++)

            for(int j = 0; j < i; j++)

            {

                if(dp[j] && dict.count(s.substr(j, i-j)) == 1)//对前i个字符进行切分时,只要有一种情况为true,则dp[i]=true 

                {

                    dp[i] = true;

                    break;

                }

            }

        return dp[len];

        

    }

    

    bool wordBreak2(string s, unordered_set<string> &dict) {

        if(s.size() == 0 || dict.size() == 0)

            return false;

        int len = s.size();

        vector<bool> dp(len+1, false);//保存状态,dp[i]表示前i个字符是否可以进行wordBread 

        dp[0] = true;

        for(int i = 0; i < len; i++)

            if(dp[i])

            {

                for(int j = 1; j <= len-i; j++)

                    if(dict.count(s.substr(i, j)) == 1)

                        dp[i+j] = true;

            }



        return dp[len];

        

    }

    

    //DP:自顶向下, 

    int wordBreak3_core(string s, unordered_set<string> &dict, int *dp)

    {

        int len = s.size();

        if(dp[len] >= 0)

            return dp[len];//如果值已经改变即不再是初始值,说明dp[len]已经求得,直接返回即可,不必再求 

        int isBreak;

        if(len == 0)

            isBreak = 1;

        else

        {

            int ret = 0;

            for(int i = 0; i < len; i++)

            {

                if(wordBreak3_core(s.substr(0, i), dict, dp) == 1 && dict.count(s.substr(i, len-i)) == 1)

                {

                    ret = 1;

                    break;

                }

                                   

            }

            isBreak = ret;

            

        }

        dp[len] = isBreak;

        return isBreak;        

    }

    //DP:自顶向下,

    bool wordBreak3(string s, unordered_set<string> &dict) 

    {

        if(s.size() == 0 || dict.size() == 0)

            return false;

        int len = s.size();

        int *dp = new int[len+1];//保存状态,dp[i]表示前i个字符是否可以进行wordBread

        for(int i = 0; i <= len; i++)

            dp[i] = -1;//每个状态进行初始化 

        int ret = wordBreak3_core(s, dict, dp);

        delete [] dp;

        return ret;

        

    }

    



};



int main(void)

{

    string s("leetcode");

    unordered_set<string> dict;

    dict.insert("leet");

    dict.insert("code");

    Solution solution;

    bool ret = solution.wordBreak3(s, dict);

    cout<<ret<<endl;



    return 0;

}

网上还有通过trie树实现的,这里直接引用http://www.iteye.com/topic/1132188#2402159,就不多写了

代码如下:

class Solution {

public:



    class Node {

    public:

        Node* next[26];

        bool end;

        Node(): end(false) { for (int i = 0; i < 26; i++) next[i] = NULL;}

        void insert(string a) {

            Node * cur = this;

            for (int i = 0; i < a.size(); i++) {

                if (cur->next[a[i]-'a'] == NULL) {

                    cur->next[a[i]-'a'] = new Node();

                }

                cur = cur->next[a[i]-'a'];

            }

            cur->end = true;

        }

        ~Node () {

            for (int i = 0;i < 26; i++) delete next[i];

        }

    };

    

    bool wordBreak(string s, unordered_set<string> &dict) {

        Node root;

        for (auto it = dict.begin(); it != dict.end(); ++it) {

            root.insert(*it);

        }

        

        vector<bool> v(s.size(), false);

        findMatch(s, &root, 0, v);

        for (int i = 0; i < s.size(); i++) 

            if (v[i]) findMatch(s, &root, i+1, v);

        return v[s.size() - 1];

    }

    

    void findMatch(const string& s, Node* cur, int start, vector<bool> &v) {

        int i = start, n = s.size();

        while (i < n) {

            if (cur->next[s[i] - 'a'] != NULL) {

                if (cur->next[s[i] - 'a']->end) v[i] = true;

                cur = cur->next[s[i] - 'a'];

            }

            else break;

            i++;

        }

        

    }

};

你可能感兴趣的:(LeetCode)