Problem
Solution
题意为:给你一个非空字符串s,一个单词列表,让你判断是否能把s分割成若干单词(单词必须在所给列表里出现过)
dp[i]表示s[0,i]是否能正确分割。
那dp[i]怎么算呢?我们只需要遍历j属于[0,i],用j把[0,i]的字符串分割成两部分,[0,j]和[j+1,i],[0,j]区间是否能正确分割直接用dp[j]就可以知道,然后再去查找[j+1,i]子串是否在所给列表中就可以了,若对某个j该子串在列表中,则dp[i]可以被正确分割;若对所有j都无法找到,则dp[i]不能被正确分割。
考虑初始的边界情况,用一次顺序遍历,找到最小的k,使[0,k]子串在所给列表中,并置dp[k]=ture。若k超过了原串长度,则可以直接返回false。
把原来的vector都存到set里,可以加速查询。
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
set<string> ss;
int len=wordDict.size();
for(int i=0;i<len;++i) ss.insert(wordDict[i]);
int n=s.length();
bool dp[n];
memset(dp,false,sizeof(dp));
int k;
for(k=1;k<=n;++k)
{
string sub=s.substr(0,k);
if(ss.count(sub)) break;
}
if(k>n) return false;
dp[k-1]=true;
for(int i=k;i<n;++i)
{
//这个if单独测一下[0,i]是否是列表里的串 若是则不用分割了 否则进入第二个for循环进行分割
if(ss.count(s.substr(0,i+1))){
dp[i]=true;
continue;
}
for(int j=0;j<=i;++j)
{
if(dp[j])
{
string sub=s.substr(j+1,i-j);
if(ss.count(sub))
{
dp[i]=true;
break;
}
}
}
}
return dp[n-1];
}
};