package class07; import java.util.HashSet; public class Code05_WorldBreak { /* * * 假设所有字符都是小写字母. 大字符串是str. arr是去重的单词表, 每个单词都不是空字符串且可以使用任意次. * 使用arr中的单词有多少种拼接str的方式. 返回方法数. * */ public static int ways(String str, String[] arr) { HashSet set = new HashSet<>(); for (String candidate : arr) { set.add(candidate); } return process(str, 0, set); } // 所有的可分解字符串,都已经放在了set中 // str[i....] 能够被set中的贴纸分解的话,返回分解的方法数 public static int process(String str, int i, HashSet set) { if (i == str.length()) { // 没字符串需要分解了! return 1; } // i....还有字符串需要分解 int ways = 0; // [i ... end] 前缀串 每一个前缀串 for (int end = i; end < str.length(); end++) { String pre = str.substring(i, end + 1);// [) if (set.contains(pre)) { ways += process(str, end + 1, set); } } return ways; } public static int ways1(String str, String[] arr) { if (str == null || str.length() == 0 || arr == null || arr.length == 0) { return 0; } HashSet map = new HashSet<>(); for (String s : arr) { map.add(s); } return f(str, map, 0); } public static int f(String str, HashSet map, int index) { if (index == str.length()) { return 1; } int ways = 0; for (int end = index; end < str.length(); end++) { if (map.contains(str.substring(index, end + 1))) { ways += f(str, map, end + 1); } } return ways; } public static int ways2(String str, String[] arr) { if (str == null || str.length() == 0 || arr == null || arr.length == 0) { return 0; } HashSet map = new HashSet<>(); for (String s : arr) { map.add(s); } int N = str.length(); int[] dp = new int[N + 1]; dp[N] = 1; for (int i = N - 1; i >= 0; i--) { for (int end = i; end < N; end++) { if (map.contains(str.substring(i, end + 1))) { dp[i] += dp[end + 1]; } } } return dp[0]; } public static class Node { public boolean end; public Node[] nexts; public Node() { end = false; nexts = new Node[26]; } } public static int ways3(String str, String[] arr) { if (str == null || str.length() == 0 || arr == null || arr.length == 0) { return 0; } Node root = new Node(); for (String s : arr) { char[] chs = s.toCharArray(); Node node = root; int index = 0; for (int i = 0; i < chs.length; i++) { index = chs[i] - 'a'; if (node.nexts[index] == null) { node.nexts[index] = new Node(); } node = node.nexts[index]; } node.end = true; } return g(str.toCharArray(), root, 0); } // str[i...] 被分解的方法数,返回 public static int g(char[] str, Node root, int i) { if (i == str.length) { return 1; } int ways = 0; Node cur = root; // i...end for (int end = i; end < str.length; end++) { int path = str[end] - 'a'; if (cur.nexts[path] == null) { break; } cur = cur.nexts[path]; if (cur.end) { // i...end ways += g(str, root, end + 1); } } return ways; } public static int ways4(String s, String[] arr) { if (s == null || s.length() == 0 || arr == null || arr.length == 0) { return 0; } Node root = new Node(); for (String str : arr) { char[] chs = str.toCharArray(); Node node = root; int index = 0; for (int i = 0; i < chs.length; i++) { index = chs[i] - 'a'; if (node.nexts[index] == null) { node.nexts[index] = new Node(); } node = node.nexts[index]; } node.end = true; } char[] str = s.toCharArray(); int N = str.length; int[] dp = new int[N + 1]; dp[N] = 1; for (int i = N - 1; i >= 0; i--) { Node cur = root; for (int end = i; end < N; end++) { int path = str[end] - 'a'; if (cur.nexts[path] == null) { break; } cur = cur.nexts[path]; if (cur.end) { dp[i] += dp[end + 1]; } } } return dp[0]; } // 以下的逻辑都是为了测试 public static class RandomSample { public String str; public String[] arr; public RandomSample(String s, String[] a) { str = s; arr = a; } } // 随机样本产生器 public static RandomSample generateRandomSample(char[] candidates, int num, int len, int joint) { String[] seeds = randomSeeds(candidates, num, len); HashSet set = new HashSet<>(); for (String str : seeds) { set.add(str); } String[] arr = new String[set.size()]; int index = 0; for (String str : set) { arr[index++] = str; } StringBuilder all = new StringBuilder(); for (int i = 0; i < joint; i++) { all.append(arr[(int) (Math.random() * arr.length)]); } return new RandomSample(all.toString(), arr); } public static String[] randomSeeds(char[] candidates, int num, int len) { String[] arr = new String[(int) (Math.random() * num) + 1]; for (int i = 0; i < arr.length; i++) { char[] str = new char[(int) (Math.random() * len) + 1]; for (int j = 0; j < str.length; j++) { str[j] = candidates[(int) (Math.random() * candidates.length)]; } arr[i] = String.valueOf(str); } return arr; } public static void main(String[] args) { char[] candidates = { 'a', 'b' }; int num = 20; int len = 4; int joint = 5; int testTimes = 30000; boolean testResult = true; for (int i = 0; i < testTimes; i++) { RandomSample sample = generateRandomSample(candidates, num, len, joint); int ans1 = ways1(sample.str, sample.arr); int ans2 = ways2(sample.str, sample.arr); int ans3 = ways3(sample.str, sample.arr); int ans4 = ways4(sample.str, sample.arr); if (ans1 != ans2 || ans3 != ans4 || ans2 != ans4) { testResult = false; } } System.out.println(testTimes + "次随机测试是否通过:" + testResult); } }