描述:
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”.
思路:
刚开始拿到这题时,直接用循环的方式来做,即用一个while((index=s.indexOf(str))!=-1)将所有符合要求的str穷举出来,一边穷举一边删除已经出现的字符串,但是,对s=”aaaaaaa”,setArr={“aaaa”,”aa”,”aaa”}这种测试用例就没招了,很显然到”aa”时已经将s删的只剩下”a”了,结果肯定不行。这种方法的缺点是不能记忆已经产生的结果并推倒重来。
关于推倒重来,回溯法倒是不错,就像八皇后问题那样,但是问题不是变得越来越复杂了么。
最后,还是用动态规划解决了该问题,先从第一个字符开始比对以第一个字符开始的字符串和set里面的字符串进行比对,如果有相同的字符串就将(i+str.length())处标记为true,依次类推,但只有在第i位已经被标记为true的位置才可以作为比对的开始位置,就像接力赛一样。最后能接力到最后的话就表示字符串可以分解为字典集合里面的元素。
感觉还是代码更好理解,直接上代码:
代码:
public boolean wordBreak(String s, Set<String> wordDict) {
if(s==null)
return true;
BitSet set=new BitSet();
set.set(0);//第一个肯定是匹配的,否则游戏还怎么玩?
int len=s.length();
int tempLen=0,endIndex=0;
for(int i=0;i<len;i++)
{
//保证后面的匹配都是在前面匹配的基础上
if(!set.get(i))进行
continue;
//在前面标记的基础上标记所有可能的匹配
for(String str:wordDict)
{
tempLen=str.length();
endIndex=i+tempLen;
if(endIndex>len)//超出了要标记的范围
continue;
if(set.get(endIndex))
continue;
if(s.subSequence(i, endIndex).equals(str))
set.set(endIndex);
}
}
//在前面标记的基础上能否到达最后一站就决定了是否能成功匹配
return set.get(len);
}
原文地址:http://blog.csdn.net/mnmlist/article/details/46558833