題意:給定一個字符串和一個單詞序列,判斷該字符串能不能分成若干個子串,且每個子串是單詞序列的詞。給出所有分法。
解法:分爲兩個步驟:首先判斷是否能分,然後再給出所有的分法。
判斷是否能分:從後向前掃描,如果從某一位置到字符串的結尾在單詞序列裏,或者某一序列在單詞序列並且這一序列的下一個字母已經被驗證能分,則isOk[i]=true,只要判斷isOk[0]是否爲true就可以。
給出所有分法:文字講述比較繞。用vector<vector<string>>代表每一個下標開始對應的分法,最後只要返回vector[0]即可。如何記錄分法?和剛纔一樣,分成兩種情況。對於某一個位置,如果到結尾這一段在字典裏,直接放到vector<string>裏,如果從該位置到另一個非結尾的位置再字典裏,如果結尾的位置下一位置的vector<string>不爲空,則把這個單詞加上那個下一個位置的vector<string>的每一個string進行連接,放在該位置對應的vector<string>裏。返回vector[0]即可。
代碼:
vector<string> wordBreak(string s, unordered_set<string>& wordDict)
{
int i,j,k,length=s.length();
vector<vector<string>> ans;
vector<string> temp;
vector<bool> isOk;
for(i=0; i<length; i++)
{
ans.push_back(temp);
isOk.push_back(false);
}
for(i=length-1;i>=0;i--)
{
for(j=i;j<length;j++)
{
if(wordDict.find(s.substr(i,j-i+1))!=wordDict.end())
{
if(j==length-1 || isOk[j+1]==true)
{
isOk[i]=true;
break;
}
}
}
}
if(isOk[0]==false) return temp;
for(i=length-1; i>=0; i--)
{
for(j=i; j<length; j++)
{
if(wordDict.find(s.substr(i,j-i+1))!=wordDict.end())
{
if(j==length-1) ans[i].push_back(s.substr(i,j-i+1));
else if(ans[j+1].size()>0)
{
temp=ans[j+1];
for(k=0; k<temp.size(); k++)
{
string tempString=s.substr(i,j-i+1);
tempString+=" ";
tempString+=ans[j+1][k];
ans[i].push_back(tempString);
}
}
}
}
cout<<i<<" "<<ans[i].size()<<endl;
}
return ans[0];
}