動態規劃——字串分割(Word Break)

遙遠的歌s發表於2020-10-06

題目描述
給定一個字串s和一組單詞dict,判斷s是否可以用空格分割成一個單詞序列,使得單詞序列中所有的單詞都是dict中的單詞(序列可以包含一個或多個單詞)。
例如:
給定s=“nowcode”;
dict=[“now”, “code”].
返回true,因為"nowcode"可以被分割成"now code".

題目連結
字串分割

這是一個典型的動態規劃的問題,首先想到的是暴力破解,但是需要考慮的情況實在是太多,所以這裡使用動態規劃來求解問題。
這個題中,先分析狀態F(i),可以用它來表示這個字串中前i個字元是否可以被分割。比如上題中的例子
在這裡插入圖片描述
這裡可以知道後面的狀態是和前面字元是否可以分割的狀態有關的,如果前面的某個狀態中能表示可以分割,那麼我只需要考慮這個狀態後面的字串是否可以分割,顯然這需要迴圈來實現。
還是上述例子,開始時遍歷到"now"的時候,即F(3)的狀態我們可以給成true,表示可以分割出來,當第四次迴圈的時候,迴圈遍歷到3的時候,是true,但是"c"不存在於字典中,那麼繼續進行第五次迴圈,當再次迴圈到F(3)的時候,發現後面的字串是"co",依然不存在字典中,繼續,直到第7次迴圈時,當迴圈到F(3)時候為true,再看第4到第7個字元是"code"發現在字典中,那麼F(7)的狀態給true,最終我們只需要返回這個狀態就可以了。

這樣得出狀態轉移方程:
F(i): true{j <i && F(j) && substr[j+1,i]能在詞典中找到}
在j小於i中,只要能找到一個F(j)為true,並且從j+1到i之間的字元能在詞典中找到,則F(i)為true

AC程式碼

class Solution {
public:
    bool wordBreak(string s, unordered_set<string> &dict) {
    	//所給s為空,則返回false
        if (s.empty()){
            return false;
        }
        //所給字典為空,則返回false
        if (dict.empty()){
            return false;
        }
        //建立dp陣列,存貯狀態
        vector<bool> dp(s.size() + 1,false);
        dp[0] = true;//初始化di0個狀態為true
        //外層迴圈,i表示前i個字元是否可以被分割
        for(int i = 1;i<=s.size();i++)
        {
        	//內層迴圈表示F(j)可以被分割,再看s中第j+1到i的字元是否可以被分割
            for(int j = 0;j<i;j++)
            {
            	//當f(j)可以被分割,則再看(j+1,i)的字元是否可以被分割
            	//若可以被分割,則將當前F(i)的狀態置為true,表示可以被分割,並且跳出內層迴圈
                if(dp[j] && dict.find(s.substr(j,i - j)) != dict.end())
                {
                    dp[i] = true;
                    break;//這裡的跳出表示我只要找到一個滿足分割的情況就跳出迴圈
                }
            }
        }
        return dp[s.size()];//返回最後一個字元位置的狀態,表示整個字串是否可以被分割
    }
};

相關文章