publicStringlongestWord(String[] words){String res ="";if(words.length ==0)return res;List<String> base =Arrays.asList(words);for(String target : words){List<String> list =newArrayList<>();//复制一份单词列表,并且移除这个目标单词本身Collections.addAll(list,newString[base.size()]);Collections.copy(list, base);
list.remove(target);if(check(target, list)){//有更长的,选更长的if(target.length()> res.length()) res = target;//单词长度相等,选字典序小的elseif(target.length()== res.length()&& target.compareTo(res)<0){
res = target;}}}return res;}/**
* @param target 目标单词
* @param list 单词列表(已经排除了目标单词本身)
* @return
*/publicbooleancheck(String target,List<String> list){if(target.length()==0)returntrue;//每次都剩下单词,是否完美切分出来for(int i =0; i <= target.length(); i++){//注意 =号 可以取到末尾 substring 取头不取尾 ,取到len-1位置,取完整个字符// System.out.printf("%s--->%s\n", target, target.substring(0, i));//当前切出来的单词在单词列表中&&剩下的单词也能在单词列表中找到(可能需要再切分)if(list.contains(target.substring(0, i))&&check(target.substring(i), list))returntrue;}returnfalse;}
方法3:动态规划
publicStringlongestWord(String[] words){String res ="";List<String> wordList =Arrays.asList(words);
wordList.sort((a, b)-> a.length()== b.length()? a.compareTo(b): b.length()- a.length());for(String target : wordList){if(check(target, wordList))return target;}return res;}privatebooleancheck(String target,List<String> wordList){int n = target.length();if(n ==0)returnfalse;System.out.println(target);boolean[] f =newboolean[n];for(int i =0; i < n; i++){//排除自生的结果,先切这部分if(i < n -1&& wordList.contains(target.substring(0, i +1))){System.out.printf("1:%s\n", target.substring(0, i +1));
f[i]=true;continue;}for(int j = i -1; j >=0; j--){System.out.printf("2:%s\n", target.substring(j +1, i +1));//如dogwalker时, f[2] = dog 为true [j+1,i+1] = walk => f[6] = true 同理=> f[8] = trueif(f[j]&& wordList.contains(target.substring(j +1, i +1))){
f[i]=true;break;}}}return f[n -1];}
方法4:字典树+回溯
TrieNode root;publicStringlongestWord(String[] words){this.root =newTrieNode();String res ="";List<String> wordList =Arrays.asList(words);//排序好,第一个返回的即是结果
wordList.sort((a, b)-> a.length()== b.length()? a.compareTo(b): b.length()- a.length());//构造字典树for(String word : wordList)insert(word);for(String word : wordList){TrieNode cur = root;int n = word.length();for(int i =0; i < n; i++){char c = word.charAt(i);//排除掉自己组成自己,当前遍历到的字符是个单词,且剩余部分可以再次被切分if(i < n -1&& cur.children[c -'a'].isEnd &&canSplitToWord(word.substring(i +1))){return word;}
cur = cur.children[c -'a'];}}return res;}/**
* 当前的单词可以被切分,在wordList中找到
*
* @param remain
* @return
*/privatebooleancanSplitToWord(String remain){//当没有可以切分的了 返回Trueif(remain.equals(""))returntrue;TrieNode cur = root;for(int i =0; i < remain.length(); i++){char c = remain.charAt(i);//拿到当前的字符if(cur.children[c -'a']==null)returnfalse;//这个节点找不到//当前的节点是个单词,且剩余部分可以再次被切分if(cur.children[c -'a'].isEnd &&canSplitToWord(remain.substring(i +1))){returntrue;}
cur = cur.children[c -'a'];}returnfalse;}/**
* Trie树插入一个单词
*
* @param word
*/privatevoidinsert(String word){TrieNode cur = root;for(char c : word.toCharArray()){if(cur.children[c -'a']==null){
cur.children[c -'a']=newTrieNode();}
cur = cur.children[c -'a'];}
cur.isEnd =true;}/**
* 构建字典树的结构
*/classTrieNode{privateTrieNode[] children;privateboolean isEnd;//当前的字符是否是一个单词的结尾publicTrieNode(){this.children =newTrieNode[26];this.isEnd =false;}}
方法5:字典树+回溯(HashMap)
TrieNode root;publicStringlongestWord(String[] words){this.root =newTrieNode();List<String> wordList =Arrays.asList(words);//排序好,第一个返回的即是结果
wordList.sort((a, b)-> a.length()== b.length()? a.compareTo(b): b.length()- a.length());//构造字典树for(String word : wordList)insert(word);for(String word : wordList){TrieNode cur = root;int n = word.length();for(int i =0; i < n; i++){char c = word.charAt(i);//排除掉自己组成自己,当前遍历到的字符是个单词,且剩余部分可以再次被切分if(i < n -1&& cur.next.get(c).isEnd &&canSplitToWord(word.substring(i +1))){return word;}
cur = cur.next.get(c);}}return"";}/**
* 当前的单词可以被切分,在wordList中找到
*
* @param remain
* @return
*/privatebooleancanSplitToWord(String remain){//当没有可以切分的了 返回Trueif(remain.equals(""))returntrue;TrieNode cur = root;for(int i =0; i < remain.length(); i++){char c = remain.charAt(i);//拿到当前的字符if(!cur.next.containsKey(c))returnfalse;//这个节点找不到//当前的节点是个单词,且剩余部分可以再次被切分if(cur.next.get(c).isEnd &&canSplitToWord(remain.substring(i +1))){returntrue;}
cur = cur.next.get(c);}returnfalse;}privatevoidinsert(String word){TrieNode cur = root;for(char c : word.toCharArray()){if(!cur.next.containsKey(c)){TrieNode t =newTrieNode();
cur.next.put(c, t);}
cur = cur.next.get(c);}
cur.isEnd =true;}classTrieNode{Map<Character,TrieNode> next =newHashMap<>();boolean isEnd =false;}