zoukankan      html  css  js  c++  java
  • 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++;
            }
            
        }
    };
  • 相关阅读:
    方法
    逻辑运算符/三元运算符/Scanner
    多线程线程状态和案例演示
    实现多线程的两种方式
    初识多线程
    IO流一些问题的总结
    IO流—其他流
    厦门Android开发三年,工资不到1w,敢问路在何方?
    二本渣渣考研失败,幸得知乎内推,成功拿下Android开发offer!
    2020Android面试心得,已拿到offer
  • 原文地址:https://www.cnblogs.com/mickole/p/3672108.html
Copyright © 2011-2022 走看看