1. 程式人生 > >演算法設計與分析》第十週作業

演算法設計與分析》第十週作業

《演算法設計與分析》第十週作業

標籤(空格分隔): 課堂作業

文章目錄

姓名:李**
學號: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。這樣就應該清楚以可分解位置為下標的詞應該歸到下一詞的開頭,而不是上一個詞的結尾。
  由此推出狀態遷移方程為:
   f

o r   i   f r o m   1
  t o   l e n g t h :
for i from 1 to length:
     f o r   j   f r o m   i 1   t o   0 : for j from i-1 to 0:
       i f ( v a l i d [ j ]   i s   t r u e   a n d   s u b s t r i n g ( j   t o   i )   i s   i n   d i c t i o n a r y ) : if (valid[j] is true and substring(j to i) is in dictionary):
         v a l i d [ i ] = t r u e valid[i] = true

具體實現

下標為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];
    }
};