标签:
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"
.
思路分析:这题如果暴力匹配,从前向后扫描s,看是否可以和dict中的词匹配,可以得到o(n^2)的solution。为了减少重复计算,我们想到用DP,从先向后保存判断是否可以segment的结果给后面复用。于是我们定义数组canSegmented,canSegmented[i]表示s[0...i]能否被segment,我们可以在最前面增加一个dummy字符,假设已经被dict包含,即canSegmented[0] = ture. 然后从前向后计算canSegmented[i],递推方程为
canSegmented[i] = true if canSegmented[k] == true 并且 s[k+1,i]在dictionary里面, 0=<k<i(注意k是尝试划分点,k=0就是不做划分)
= false if no such k exist.(也就是所有的划分都无法满足segment的条件)
k是我们尝试划分s[0...i]的位置,如果划分位置的标记数组值为true并且后面部分s[k+1,i]也被字典包含,则划分成功。如果所有的划分点都失败,则canSegmented[i]为false。有了递推方程,实现就很容易了,从前向后计算数组的元素值,最后返回canSegmented[s.length() - 1]。这题实现要注意java的substring(begin, end)函数是begin被包含,end不被包含。
AC Code
public class Solution { public boolean wordBreak(String s, Set<String> dict) { s = "#" + s; boolean[] canSegmented = new boolean[s.length()]; canSegmented[0] = true; for(int i = 1; i < s.length(); i++){ for(int k = 0; k < i; k++){ canSegmented[i] = canSegmented[k] && dict.contains(s.substring(k + 1, i + 1)); if(canSegmented[i]) break; } } return canSegmented[s.length() - 1]; } }
标签:
原文地址:http://blog.csdn.net/yangliuy/article/details/43054277