演算法設計與分析》第十週作業
《演算法設計與分析》第十週作業
標籤(空格分隔): 課堂作業
文章目錄
姓名:李**
學號:16340114
題目:Word Break(https://leetcode.com/problems/word-break)
題目概要
給定一個無分隔符的字串和一個字典,問是否能將字串分解成字典中含有的詞。
思路
給定位置i,定義該下標"可分解"的含義為:從0到該下標的子字串(不包括i)是可以被分解的。
要判斷一個位置i是否可分解,就要判斷上一個可分解的位置j到當前位置i(包含j不包含i)所分割形成的詞是否在字典中,如果存在這樣的j,那麼位置i就是可分解的,如果不存在,那麼位置i就是不可分解。最終答案就是下標為字串長度L的位置是否可分解。
用符號的方式有點難說清楚,舉個例子就好了。字串為"helloworld",位置0是可分解的,因為下標為0的位置之前是長度為0的串,自然可以分解,位置5是可分解的,下標為5的為w,w前的可分解位置是0,從0到5(包含0不包含5)形成的詞為hello。這樣就應該清楚以可分解位置為下標的詞應該歸到下一詞的開頭,而不是上一個詞的結尾。
由此推出狀態遷移方程為:
具體實現
下標為0的位置是可分解的,因為0位置前的空子字串是可分解的,所以把valid[0]設為true,其他位置的值設為false,然後根據狀態轉移方程寫就好了。
心得
這道題在課堂上講過,我覺得動手來實現一遍可以加深印象和對動態規劃的理解。我現在對動態規劃的認識似乎比上一週領略的要更好一點,像word break這一型別的動態規劃問題,先考慮一個任意位置i,用某種規則從位置i往前找j,根據前面的j的狀態確定當前位置i的狀態。課本習題的開餐廳那題也是這個思想。下一週想挑戰一下這道題的升級版,希望能對動態規劃有更深的認識。
原始碼:
#define isValid(word) (find(wordDict.begin(), wordDict.end(), word) == wordDict.end() ? false : true)
class Solution
{
public:
bool wordBreak(string s, vector<string>& wordDict)
{
int length = s.length();
bool* validEndAt = new bool [length+1];
for (int i = 0; i < length+1; ++i)
validEndAt[i] = false;
validEndAt[0] = true;
for (int i = 1; i <= length; ++i)
{
for (int j = i-1; j >= 0; --j)
{
if (validEndAt[j])
{
int lengthOfWord = i - j;
string word = s.substr(j, lengthOfWord);
if (isValid(word))
{
validEndAt[i] = true;
break;
}
}
}
}
return validEndAt[length];
}
};