30. Substring with Concatenation of All Words

    /*
     * 30. Substring with Concatenation of All Words
     * 2016-4-17 by Mingyang
     * 这道题目有一定的难度,我的思路是用一个map把对应的words和出现的次数写上去
     * 然后对于每一个位置就比较一下map中的个数并且更改
     * 首先第一个错误的地方是map的copy,我开始用的Hashmap a=b
     * 但是java是passing by value。所以应该新建一个object
     * 另外一个就是应该有个步长的变量
     */
     public static List<Integer> findSubstring(String s, String[] words) {
            int len=words.length;
            List<Integer> res=new ArrayList<Integer>();
            if(s==null||s.length()==0)
              return res;
            int sumLen=0;
            int singleLen=words[0].length();
            HashMap<String,Integer> map=new HashMap<String,Integer>();
            for(int i=0;i<len;i++){
              sumLen+=words[i].length();
              if(map.containsKey(words[i])){
                  map.put(words[i],map.get(words[i])+1);
              }else{
                  map.put(words[i],1);
              }
            }       
            for(int i=0;i<=s.length()-sumLen;i++){
                HashMap<String,Integer> temp=new HashMap<String,Integer>(map);
                for(int j=i;j<i+sumLen;j=j+singleLen){
                    String key=s.substring(j,j+singleLen);
                    if(temp.containsKey(key)){
                        temp.put(key,temp.get(key)-1);
                        if(temp.get(key)==0){
                            temp.remove(key);
                        }
                    }else{
                        break;
                    }
                }
                if(temp.size()==0){
                    res.add(i);
                }
            }
            return res;
        }    
     /*
     * 那么下面的代码更好!
     * http://blog.csdn.net/linhuanmars/article/details/20342851 非常难的一道题目
     */
         public List<Integer> findSubstring1(String S, String[] L) {
             // Note: The Solution object is instantiated only once and is reused by
             // each test case.
             List<Integer> res = new ArrayList<Integer>();
             if (S == null || S.length() == 0 || L == null || L.length == 0)
                 return res;
             HashMap<String, Integer> map = new HashMap<String, Integer>();
             for (int i = 0; i < L.length; i++) {
                 if (map.containsKey(L[i])) {
                     map.put(L[i], map.get(L[i]) + 1);
                 } else {
                     map.put(L[i], 1);
                 }
             }
             for (int i = 0; i < L[0].length(); i++) {
                 HashMap<String, Integer> curMap = new HashMap<String, Integer>();
                 int count = 0;
                 int left = i;
                 for (int j = i; j <= S.length() - L[0].length(); j += L[0].length()) {
                     String str = S.substring(j, j + L[0].length());
                     if (map.containsKey(str)) {
                         if (curMap.containsKey(str))
                             curMap.put(str, curMap.get(str) + 1);
                         else
                             curMap.put(str, 1);
                         if (curMap.get(str) <= map.get(str))
                         //这是正常的过程,不断加而没有越界
                             count++;
                         else {
                         //这里出现了情况,加过头了,原则上就是重新回去更新left到不越界为止
                             while (curMap.get(str) > map.get(str)) {
                                 String temp = S.substring(left,
                                         left + L[0].length());
                                 if (curMap.containsKey(temp)) {
                                     curMap.put(temp, curMap.get(temp) - 1);
                                     if (curMap.get(temp) < map.get(temp))
                                         count--;
                                 }
                                 left += L[0].length();
                             }
                         }
                         //如果count达标那么就输出正确的结果!!
                         //注意!还没结束。还要滑动窗口继续下一个计算
                         if (count == L.length) {
                             res.add(left);
                             // if(left<)
                             String temp = S.substring(left, left + L[0].length());
                             if (curMap.containsKey(temp))
                                 curMap.put(temp, curMap.get(temp) - 1);
                             count--;
                             left += L[0].length();
                         }
                     } else {
                         //只要一个不满足条件。马上清零map,然后直接滑动窗口
                         curMap.clear();
                         count = 0;
                         left = j + L[0].length();
                     }
                 }
             }
             return res;
         }
         /*
          * 总结:我的代码跟大神的代码差别就是sliding window,下面代码各种情况下都是滑动窗口
          * 所以第一个for循环每一个i的值都是要遍历完所有的长度倍数上的点,而我只要一个不合适马上跳出来,
          * 这里只要一个不合适还继续在第二层循环里面滑动窗口
          */
原文地址:https://www.cnblogs.com/zmyvszk/p/5403934.html