[leetcode]139. 单词拆分

给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。

说明:

拆分时可以重复使用字典中的单词。
你可以假设字典中没有重复的单词。
示例 1:

输入: s = "leetcode", wordDict = ["leet", "code"]
输出: true
解释: 返回 true 因为 "leetcode" 可以被拆分成 "leet code"

示例 2:

输入: s = "applepenapple", wordDict = ["apple", "pen"]
输出: true
解释: 返回 true 因为 "applepenapple" 可以被拆分成 "apple pen apple"。
     注意你可以重复使用字典中的单词。

示例 3:

输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
输出: false

思路:
采用广度优先遍历的思想
1.定义一个bool类型的数组visited,其中visited[i]表示i号位置之前的单词是否已经匹配,初始visit[0]=true.
定义一个整型队列q,初始将0压入进去。
2.定义int类型start,保存队头元素,并且将队首元素出队,表示从当前位置开始遍历。
3.遍历wordDict中的元素,依次取出元素,记录当前单词word的长度len,然后判断字符串s从start位置开始之后len个字符是否与word相同,相同的话将len+start入队,表示下一次开始验证的地方,同时标记visited[start+len]为true,表示该位置之前单词已经匹配成功。
4.不断进行2,3的操作,直到成功匹配到最后一个单词,返回true,否则返回false。

AC代码:(C++)

class Solution {
   public:
    bool wordBreak(string s, vector<string>& wordDict) {
        queue<int> q;
        vector<bool> visited(s.size() + 1, false);
        q.push(0);
        visited[0] = true;
        while (!q.empty()) {
            int levelSize = q.size();
            for (int i = 0; i < levelSize; i++) {
                int start = q.front();
                q.pop();
                for (string nextWord : wordDict) {
                    int len = nextWord.length();
                    if (s.length() < start + len)
                        continue;  //如果起点位置加上当前位置已经超出本身长度
                    if (nextWord == s.substr(start))
                        return true;  //下一个单词刚好为最后一个单词
                    if (visited[start + len]) continue;  //该位置已经访问过
                    if (s.substr(start, len) == nextWord) {  //判断能否匹配
                        q.push(start + len);
                        visited[start + len] = true;
                        // break;
                    }
                }
            }
        }
        return false;
    }
};

你可能感兴趣的:(LeetCode)