140.WordBreakII

Note:
- The same word in the dictionary may be reused multiple times in the segmentation.
- You may assume the dictionary does not contain duplicate words.
Example 1:
Input:s = "
catsanddog"wordDict =
["cat", "cats", "and", "sand", "dog"]Output:
["cats and dog",
"cat sand dog"
]
Example 2:
Input:s = "pineapplepenapple"
wordDict = ["apple", "pen", "applepen", "pine", "pineapple"]
Output:
[
"pine apple pen apple",
"pineapple pen apple",
"pine applepen apple"
]
Explanation: Note that you are allowed to reuse a dictionary word.
Example 3:
Input:s = "catsandog"
wordDict = ["cats", "dog", "sand", "and", "cat"]
Output:
[]
解题思路
这道题的解法其实跟139. Word Break一样,可以参考139. Word Break的思路 https://my.oschina.net/JiamingMai/blog/4331735 ,与139. Word Break稍有不同的是,这道题需要在此基础上将h[0][i]为true的所有情况记录起来。
时间复杂度分析
本质与139. Word Break一样,所以时间复杂度也是O(kn^2),分析过程参考 https://my.oschina.net/JiamingMai/blog/4331735
最终实现
Java 实现
public class Solution {    List<String>[] records;
    private boolean[][] h;
    private boolean[][] r;
    public List<String> wordBreak(String s, List<String> wordDict) {
        int n = s.length();
        if (!fastWordBreakInternal(s, wordDict)) {
            return new ArrayList<>();
        }
        boolean res = wordBreakInternal(s, wordDict);
        if (res) {
            return records[n];
        }
        return new ArrayList<>();
    }
    public boolean fastWordBreakInternal(String s, List<String> wordDict) {
        int n = s.length();
        h = new boolean[n+1][n+1];
        r = new boolean[n+1][n+1];
        initR(n, s, wordDict);
        h[0][0] = true;
        for (int i = 1; i <= n; i++) {
            for (int j = i; j >= 0; j--) {
                if (!h[0][i]) {
                    h[0][i] = h[0][i-j] && r[i-j][i];
                } else {
                    break;
                }
            }
        }
        return h[0][n];
    }
    public boolean wordBreakInternal(String s, List<String> wordDict) {
        int n = s.length();
        h = new boolean[n + 1][n + 1];
        r = new boolean[n + 1][n + 1];
        records = new List[n + 1];
        initR(n, s, wordDict);
        h[0][0] = true;
        for (int i = 1; i <= n; i++) {
            for (int j = i; j >= 0; j--) {
                if (h[0][i - j] && r[i - j][i]) {
                    h[0][i] = true;
                    record(i, j, s);
                }
            }
        }
        return h[0][n];
    }
    private void record(int i, int j, String s) {
        if (null == records[i]) {
            records[i] = new ArrayList<>();
        }
        String token = s.substring(i - j, i);
        if (null != records[i - j]) {
            for (String str : records[i - j]) {
                StringBuffer sb = new StringBuffer();
                sb.append(str).append(" ").append(token);
                records[i].add(sb.toString());
            }
        }  else {
            records[i].add(token);
        }
    }
    private void initR(int n, String s, List<String> wordDict) {
        for (int i = 0; i <= n; i++) {
            for (int j = i; j <= n; j++) {
                r[i][j] = r(i, j, s, wordDict);
            }
        }
    }
    private boolean r(int i, int j, String s, List<String> wordDict) {
        String token = s.substring(i, j);
        for (String word : wordDict) {
            if (word.equals(token)) {
                return true;
            }
        }
        return false;
    }
    public static void main(String[] args) {
        List<String> wordDict = new ArrayList<>();
        wordDict.add("a");
        wordDict.add("aa");
        wordDict.add("aaa");
        wordDict.add("aaaa");
        wordDict.add("aaaaa");
        wordDict.add("aaaaaa");
        wordDict.add("aaaaaaa");
        wordDict.add("aaaaaaaa");
        wordDict.add("aaaaaaaaa");
        wordDict.add("aaaaaaaaaa");
        String s = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
        Solution solution = new Solution();
        List<String> res = solution.wordBreak(s, wordDict);
        res.stream().forEach(str -> {System.out.println(str);});
    }
}
注意到代码main方法里面的那个例子,输入是一大串连续的a只有中间一个b,这种情况如果直接边算边记录的话会超时,所以这里有个trick就是先快速判断输入的字符串能否拆解,如果不能就直接输出一个空的List即可,这个例子正好就是不能拆解的case。
以上是 140.WordBreakII 的全部内容, 来源链接: utcz.com/z/517997.html








