Substring with Concatenation of All Words

题目描述:

You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) ins that is a concatenation of each word inwords exactly once and without any intervening characters.

For example, given:
s: "barfoothefoobarman"
words: ["foo", "bar"]

You should return the indices: [0,9].
(order does not matter).

最笨的办法就是枚举出来所有的子集,然后再从S中得到相应的index、不出意外超时了。

public List
   
   
    
     findSubstring(String s, String[] words) {
	List
    
    
     
      list=new ArrayList
     
     
      
      ();
	for (int i = 0; i < words.length; i++) {
		list.add(words[i]);
	}
	StringBuilder sb=new StringBuilder();
	List
      
      
       
        wordList=new ArrayList
       
       
         (); List 
        
          result=new ArrayList 
         
           (); getAllSubString(list, sb, wordList); for (int i = 0; i < wordList.size(); i++) { int index; if((index=s.indexOf(wordList.get(i)))!=-1){ result.add(index); } } return result; } public void getAllSubString(List 
          
            list,StringBuilder sb,List 
           
             result){ if(list.size()==0) result.add(sb.toString()); for(int i=0;i 
            
              newList=new ArrayList 
             
               (list); newList.remove(list.get(i)); getAllSubString(newList, newSb, result); } } 
              
             
            
           
          
         
       
      
      
     
     
    
    
   
   

后来用hashtable,创建map<string,integer>,int记录单词的个数,这样也超时了。此时的复杂度是O(m*n):

public List
   
   
    
     findSubstring(String s, String[] words) {
    int n=words.length;
    int len=words[0].length();
    Map
    
    
     
      map=new HashMap
     
     
      
      ();
    List
      
      
       
        result=new ArrayList
       
       
         (); for(int i=0;i 
        
          0){ map.put(str, map.get(str) - 1); cnt++; start += len; if (start + len > s.length()) break; //注意越界 str = s.substring(start, start + len); } if (cnt == n) { result.add(i); } if(cnt>0){ map.clear(); for(int j=0;j 
          
         
       
      
      
     
     
    
    
   
   

后来参考了别人的做法,实在是巧妙。

public List
    
    
     
      findSubstring(String S, String[] L) {  
    List
     
     
      
       ret = new ArrayList
      
      
       
       ();  
    int slen = S.length(), llen = L.length;  
    if (slen <= 0 || llen <= 0)  
        return ret;  
    int wlen = L[0].length();  

    // get the words' map  
    HashMap
       
       
        
         words = new HashMap
        
        
          (); for (String str : L) { if (words.containsKey(str)) { words.put(str, words.get(str) + 1); } else { words.put(str, 1); } } for (int i = 0; i < wlen; ++i) { int left = i, count = 0; HashMap 
         
           tmap = new HashMap 
          
            (); for (int j = i; j <= slen - wlen; j += wlen) { String str = S.substring(j, j + wlen); if (words.containsKey(str)) { if (tmap.containsKey(str)) { tmap.put(str, tmap.get(str) + 1); } else { tmap.put(str, 1); } if (tmap.get(str) <= words.get(str)) { count++; } else { // too many words, push the 'left' forward while (tmap.get(str) > words.get(str)) { String tmps = S.substring(left, left + wlen); tmap.put(tmps, tmap.get(tmps) - 1); if (tmap.get(tmps) < words.get(tmps)) { // if affect the count count--; } left += wlen; } } // get the answer if (count == llen) { ret.add(left); // it's better to push forward once String tmps = S.substring(left, left + wlen); tmap.put(tmps, tmap.get(tmps) - 1); count--; left += wlen; } } else { // not any match word tmap.clear(); count = 0; left = j + wlen; } } } return ret; } 
           
          
        
       
       
      
      
     
     
    
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值