思路:
把所有的子串存入Hashtable,对原字符串进行O(n2)的搜索,看能不能用完Hashtable所有的字串
本题用了不是很好的暴力法压线通过,下次改成用KMP的方法重写一遍。现在还太弱了,不会KMP。。。T^T
还遇到了很奇怪的问题,在代码中注释体现。
package Level3; import java.util.ArrayList; import java.util.Hashtable; /** * Substring with Concatenation of All Words * You are given a string, S, and a list of words, L, that are all of the same length. Find all starting indices of substring(s) in S that is a concatenation of each word in L exactly once and without any intervening characters. For example, given: S: "barfoothefoobarman" L: ["foo", "bar"] You should return the indices: [0,9]. (order does not matter). */ public class S30 { public static void main(String[] args) { String S = "barfoothefoobarman"; String[] L = {"foo", "bar"}; // String S = "a"; // String[] L = {"a"}; System.out.println(findSubstring(S, L)); } // 用暴力法压线通过,未来应该用类似KMP的方法降低复杂度! public static ArrayList<Integer> findSubstring(String S, String[] L) { ArrayList<Integer> ret = new ArrayList<Integer>(); Hashtable<String, Integer> ht = new Hashtable<String, Integer>(); // 把L中的string全部添加入hashtable for (String str : L) { if(ht.containsKey(str)){ ht.put(str, ht.get(str)+1); }else{ ht.put(str, 1); } } int wordLen = L[0].length(); int numberOfWords = L.length; // Brute force法比较 for(int i=0; i<=S.length()-numberOfWords*wordLen; i++){ // 每次要基于原hashtable新建一个hashtable Hashtable<String, Integer> table = new Hashtable<String, Integer>(ht); int cnt = 0; // j每次都重复地做相同的工作 for(int j=i; j<=i+numberOfWords*wordLen-wordLen; j+=wordLen){ String substr = S.substring(j, j+wordLen); if(table.containsKey(substr)){ // 如果只用这一句会TLE // table.put(substr, table.get(substr)-1); // 改成这样就能压线AC int times = table.get(substr); if(times == 1) table.remove(substr); else table.put(substr, times - 1); cnt++; }else{ break; } } if(cnt == numberOfWords){ ret.add(i); } } return ret; } }
找到压线通过的方法:http://www.cnblogs.com/lichen782/archive/2013/07/06/leetcode_SubstringwithConcatenationofAllWords.html
KMP的初步认识: http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html
一个基于KMP的解决方法:http://n00tc0d3r.blogspot.com/2013/06/substring-with-concatenation-of-all.html
import java.util.*; public class Solution { public List<Integer> findSubstring(String S, String[] L) { List<Integer> ret = new ArrayList<Integer>(); int m = L.length; if(m == 0) { return ret; } int n = L[0].length(); Hashtable<String, Integer> ht = new Hashtable<String, Integer>(); for(String word : L) { Integer cnt = ht.get(word); if(cnt == null) { ht.put(word, 1); } else { ht.put(word, cnt+1); } } for(int i=0; i<=S.length()-n*m; i++) { Hashtable<String, Integer> tmp = new Hashtable<String, Integer>(); int j = 0; for(j=0; j<m; j++) { int k = i + j*n; // n-characters interval String substr = S.substring(k, k+n); Integer cntInHt = ht.get(substr); // check if substr in Hashtable Integer cntInTmp = tmp.get(substr); // check if substr in temporary Ht // must be in the original Hashtable and found cnts of character should be less than all available characters if(cntInHt != null && (cntInTmp == null || cntInTmp < cntInHt)) { if(cntInTmp == null) { tmp.put(substr, 1); } else { tmp.put(substr, cntInTmp+1); } } else { break; } } if(j == m) { // found all words in L ret.add(i); } } return ret; } }