Leetcode Word break I, II

Word break I

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层面和palindrome partition一模一样,一维就够了。但是对于长字符串会超时,这个时候就需要用dict建立prefix tree来剪枝,当前substring已经不是一个valid prefix时,就可以停止往后判断。
其实c++的题目完全不需要优化就过了呵呵呵。。。
[code]

public class Solution {
    public boolean wordBreak(String s, Set<String> dict) {
        if(s==null || s.length()==0)return true;
        if(dict.size()==0)return false;
        int n=s.length();
        dp=new int[n];
        Arrays.fill(dp,-1);
        buildPrefixTree(dict);
        return breaks(s,0,dict)==1;
    }
    int dp[];
    PrefixTreeNode root;
    int breaks(String s, int start, Set<String> dict)
    {
        if(start==s.length())return 1;
        if(dp[start]!=-1)return dp[start];
        for(int i=start;i<s.length();i++)
        {
            if(dict.contains(s.substring(start,i+1)))
            {
                dp[start]= breaks(s,i+1,dict);
                if(dp[start]==1)return 1;
            }
            else if(PrefixTreeNode.contains(s.substring(start,i+1),0,root)==false)
            {
                dp[start]=0;
                return 0;
            }
        }
        return dp[start];
    }

    void buildPrefixTree(Set<String> dict)
    {
        root=new PrefixTreeNode('0');
        for(String s:dict)
        {
            build(s,0,root);
        }
    }

    void build(String s, int index, PrefixTreeNode node)
    {
        if(index==s.length())return;
        for(PrefixTreeNode p:node.next)
        {
            if(p.val==s.charAt(index))
            {
                build(s,index+1,p);
                return;
            }
        }
        PrefixTreeNode newNode=new PrefixTreeNode(s.charAt(index));
        node.next.add(newNode);
        build(s,index+1,newNode);
    }
}

class PrefixTreeNode
{
    ArrayList<PrefixTreeNode> next;
    char val;
    PrefixTreeNode(char c)
    {
        val=c;
        next=new ArrayList<PrefixTreeNode>();
    }

    static boolean contains(String s, int index, PrefixTreeNode node)
    {
        if(index==s.length())return true;
        for(PrefixTreeNode p:node.next)
        {
            if(p.val==s.charAt(index))
            {
                boolean t=contains(s,index+1,p);
                if(t)return true;
            }
        }
        return false;
    }
}

=========================================================

Word break II

Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each word is a valid dictionary word.
Return all such possible sentences.

For example, given
s = “catsanddog”,
dict = [“cat”, “cats”, “and”, “sand”, “dog”].

A solution is [“cats and dog”, “cat sand dog”].


遇到这种打印所有路径的问题最先考虑的就是dfs + path保存中间路径。 其实这里dp的作用更多的是保存已经遍历过的结果,ie memoization for recursive

[code]

public class Solution {
    List<String> list;
    HashMap<Integer, List<String>> dp;
    int valid[];
    public List<String> wordBreak(String s, Set<String> dict) 
    {
        list=new ArrayList<String>();
        if(s==null || s.length()==0 || dict.isEmpty())return list;
        dp=new HashMap<Integer, List<String>>();
        valid=new int[s.length()];
        Arrays.fill(valid, -1);
        StringBuffer path=new StringBuffer();
        breaks(s,0,dict,path);
        return list;
    }

    int breaks(String s, int start, Set<String> dict, StringBuffer path)
    {
        if(start==s.length())
        {
            list.add(path.toString().trim());
            if(dp.containsKey(start)==false)
            {
                List<String> temp=new ArrayList<String>();
                temp.add(new String());
                dp.put(start, temp);
            }
            return 1;
        }
        if(valid[start]!=-1)
        {
            if(dp.containsKey(start))
            {
                for(String str:dp.get(start))
                {
                    path.append(str);
                    breaks(s,s.length(),dict,path);
                    path.delete(path.length()-str.length(), path.length());
                }
            }
            return valid[start];
        }

        valid[start]=0;
        for(int i=start;i<s.length();i++)
        {
            String sub=s.substring(start,i+1);
            if(dict.contains(sub))
            {
                sub=sub+" ";
                path.append(sub);
                if(breaks(s,i+1,dict,path)==1)
                {
                    valid[start]=1;
                    if(dp.containsKey(start)==false)dp.put(start, new ArrayList<String>());
                    List<String> l=dp.get(i+1);
                    StringBuffer temp=new StringBuffer(sub);
                    for(String entry:l)
                    {
                        temp.append(entry);
                        dp.get(start).add(temp.toString());
                        temp.delete(temp.length()-entry.length(),temp.length());
                    }
                }
                path.delete(path.length()-sub.length(),path.length());
            }
        }
        return valid[start];
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值